├── .gitignore ├── .travis.yml ├── Builtin ├── Elements.py ├── LUIBlockText.py ├── LUIButton.py ├── LUICheckbox.py ├── LUIFormattedLabel.py ├── LUIFrame.py ├── LUIHorizontalLayout.py ├── LUIInitialState.py ├── LUIInputField.py ├── LUIInputHandler.py ├── LUILabel.py ├── LUILayouts.py ├── LUIObject.py ├── LUIProgressbar.py ├── LUIRadiobox.py ├── LUIRadioboxGroup.py ├── LUIRegion.py ├── LUIRoot.py ├── LUIScrollableRegion.py ├── LUISelectbox.py ├── LUISkin.py ├── LUISlider.py ├── LUISprite.py ├── LUISpriteButton.py ├── LUITabbedFrame.py ├── LUIVerticalLayout.py └── __init__.py ├── Demos ├── .gitignore ├── 01_MinimalExample.py ├── 02_SimpleConsole.py ├── B_BlockText.py ├── B_Button.py ├── B_Checkbox.py ├── B_FormattedLabel.py ├── B_Frame.py ├── B_InputField.py ├── B_Label.py ├── B_Progressbar.py ├── B_Radiobox.py ├── B_Slider.py ├── DemoFramework.py ├── README.md ├── __init__.py └── res │ ├── DemoBackground.png │ ├── LUILogo.png │ └── LUILogoBlack.png ├── LICENSE.txt ├── Misc ├── Draft.psd ├── Draft2.psd ├── Draft3.psd ├── LUIAtlasGen.py ├── LUIGenerateGrid.py ├── Metro.psd └── blank.png ├── README.md ├── Skins ├── Default │ ├── GenerateAtlas.bat │ ├── __init__.py │ ├── font │ │ ├── SourceSansPro-Black.ttf │ │ ├── SourceSansPro-BlackIt.ttf │ │ ├── SourceSansPro-Bold.ttf │ │ ├── SourceSansPro-BoldIt.ttf │ │ ├── SourceSansPro-ExtraLight.ttf │ │ ├── SourceSansPro-ExtraLightIt.ttf │ │ ├── SourceSansPro-It.ttf │ │ ├── SourceSansPro-Light.ttf │ │ ├── SourceSansPro-LightIt.ttf │ │ ├── SourceSansPro-Regular.ttf │ │ ├── SourceSansPro-Semibold.ttf │ │ └── SourceSansPro-SemiboldIt.ttf │ └── res │ │ ├── ButtonDefault.png │ │ ├── ButtonDefaultFocus.png │ │ ├── ButtonDefaultFocus_Left.png │ │ ├── ButtonDefaultFocus_Right.png │ │ ├── ButtonDefault_Left.png │ │ ├── ButtonDefault_Right.png │ │ ├── ButtonGreen.png │ │ ├── ButtonGreenFocus.png │ │ ├── ButtonGreenFocus_Left.png │ │ ├── ButtonGreenFocus_Right.png │ │ ├── ButtonGreen_Left.png │ │ ├── ButtonGreen_Right.png │ │ ├── Checkbox_Checked.png │ │ ├── Checkbox_CheckedHover.png │ │ ├── Checkbox_Default.png │ │ ├── Checkbox_DefaultHover.png │ │ ├── ColorpickerActiveColorOverlay.png │ │ ├── ColorpickerFieldHandle.png │ │ ├── ColorpickerFieldOverlay.png │ │ ├── ColorpickerHueHandle.png │ │ ├── ColorpickerHueSlider.png │ │ ├── ColorpickerPreviewBg.png │ │ ├── ColorpickerPreviewOverlay.png │ │ ├── Frame_BL.png │ │ ├── Frame_BR.png │ │ ├── Frame_Bottom.png │ │ ├── Frame_Left.png │ │ ├── Frame_Mid.png │ │ ├── Frame_Right.png │ │ ├── Frame_TL.png │ │ ├── Frame_TR.png │ │ ├── Frame_Top.png │ │ ├── HorizontalListDivider.png │ │ ├── InputField.png │ │ ├── InputField_Left.png │ │ ├── InputField_Right.png │ │ ├── Keymarker.png │ │ ├── Keymarker_Left.png │ │ ├── Keymarker_Right.png │ │ ├── ListDivider.png │ │ ├── Popup_BL.png │ │ ├── Popup_BR.png │ │ ├── Popup_Bottom.png │ │ ├── Popup_Left.png │ │ ├── Popup_Mid.png │ │ ├── Popup_Right.png │ │ ├── Popup_TL.png │ │ ├── Popup_TR.png │ │ ├── Popup_Top.png │ │ ├── ProgressbarBg.png │ │ ├── ProgressbarBg_Left.png │ │ ├── ProgressbarBg_Right.png │ │ ├── ProgressbarFg.png │ │ ├── ProgressbarFg_Finish.png │ │ ├── ProgressbarFg_Left.png │ │ ├── ProgressbarFg_Right.png │ │ ├── Radiobox_Active.png │ │ ├── Radiobox_ActiveHover.png │ │ ├── Radiobox_Default.png │ │ ├── Radiobox_DefaultHover.png │ │ ├── ScrollShadowBottom.png │ │ ├── ScrollShadowBottom_Left.png │ │ ├── ScrollShadowBottom_Right.png │ │ ├── ScrollShadowTop.png │ │ ├── ScrollShadowTop_Left.png │ │ ├── ScrollShadowTop_Right.png │ │ ├── ScrollbarHandle.png │ │ ├── ScrollbarHandle_Bottom.png │ │ ├── ScrollbarHandle_Top.png │ │ ├── Selectbox.png │ │ ├── SelectboxActive.png │ │ ├── SelectboxActive_Left.png │ │ ├── SelectboxOpen_Right.png │ │ ├── Selectbox_Left.png │ │ ├── Selectbox_Right.png │ │ ├── SelectdropDivider.png │ │ ├── Selectdrop_BL.png │ │ ├── Selectdrop_BR.png │ │ ├── Selectdrop_Bottom.png │ │ ├── Selectdrop_Left.png │ │ ├── Selectdrop_Mid.png │ │ ├── Selectdrop_Right.png │ │ ├── Selectdrop_TL.png │ │ ├── Selectdrop_TR.png │ │ ├── Selectdrop_Top.png │ │ ├── SliderBg.png │ │ ├── SliderBgFill.png │ │ ├── SliderBgFill_Left.png │ │ ├── SliderBg_Left.png │ │ ├── SliderBg_Right.png │ │ ├── SliderKnob.png │ │ ├── SunkenFrame_BL.png │ │ ├── SunkenFrame_BR.png │ │ ├── SunkenFrame_Bottom.png │ │ ├── SunkenFrame_Left.png │ │ ├── SunkenFrame_Mid.png │ │ ├── SunkenFrame_Right.png │ │ ├── SunkenFrame_TL.png │ │ ├── SunkenFrame_TR.png │ │ ├── SunkenFrame_Top.png │ │ ├── atlas.png │ │ ├── atlas.txt │ │ └── blank.png ├── Metro │ ├── GenerateAtlas.bat │ ├── LUIMetroSkin.py │ ├── __init__.py │ ├── border.png │ ├── copy_frames.py │ ├── flat.png │ ├── font │ │ ├── Roboto-Bold.ttf │ │ ├── Roboto-LICENSE.txt │ │ ├── Roboto-Light.ttf │ │ ├── Roboto-Medium.ttf │ │ └── Roboto-Thin.ttf │ └── res │ │ ├── ButtonDefault.png │ │ ├── ButtonDefaultFocus.png │ │ ├── ButtonDefaultFocus_Left.png │ │ ├── ButtonDefaultFocus_Right.png │ │ ├── ButtonDefault_Left.png │ │ ├── ButtonDefault_Right.png │ │ ├── ButtonGreen.png │ │ ├── ButtonGreenFocus.png │ │ ├── ButtonGreenFocus_Left.png │ │ ├── ButtonGreenFocus_Right.png │ │ ├── ButtonGreen_Left.png │ │ ├── ButtonGreen_Right.png │ │ ├── Checkbox_Checked.png │ │ ├── Checkbox_CheckedHover.png │ │ ├── Checkbox_Default.png │ │ ├── Checkbox_DefaultHover.png │ │ ├── ColorpickerActiveColorOverlay.png │ │ ├── ColorpickerFieldHandle.png │ │ ├── ColorpickerFieldOverlay.png │ │ ├── ColorpickerHueHandle.png │ │ ├── ColorpickerHueSlider.png │ │ ├── ColorpickerPreviewBg.png │ │ ├── ColorpickerPreviewOverlay.png │ │ ├── Draft3.psd │ │ ├── Frame_BL.png │ │ ├── Frame_BR.png │ │ ├── Frame_Bottom.png │ │ ├── Frame_Left.png │ │ ├── Frame_Mid.png │ │ ├── Frame_Right.png │ │ ├── Frame_TL.png │ │ ├── Frame_TR.png │ │ ├── Frame_Top.png │ │ ├── HorizontalListDivider.png │ │ ├── InputField.png │ │ ├── InputField_Left.png │ │ ├── InputField_Right.png │ │ ├── Keymarker.png │ │ ├── Keymarker_Left.png │ │ ├── Keymarker_Right.png │ │ ├── ListDivider.png │ │ ├── Popup_BL.png │ │ ├── Popup_BR.png │ │ ├── Popup_Bottom.png │ │ ├── Popup_Left.png │ │ ├── Popup_Mid.png │ │ ├── Popup_Right.png │ │ ├── Popup_TL.png │ │ ├── Popup_TR.png │ │ ├── Popup_Top.png │ │ ├── ProgressbarBg.png │ │ ├── ProgressbarBg_Left.png │ │ ├── ProgressbarBg_Right.png │ │ ├── ProgressbarFg.png │ │ ├── ProgressbarFg_Finish.png │ │ ├── ProgressbarFg_Left.png │ │ ├── ProgressbarFg_Right.png │ │ ├── Radiobox_Active.png │ │ ├── Radiobox_ActiveHover.png │ │ ├── Radiobox_Default.png │ │ ├── Radiobox_DefaultHover.png │ │ ├── ScrollShadowBottom.png │ │ ├── ScrollShadowBottom_Left.png │ │ ├── ScrollShadowBottom_Right.png │ │ ├── ScrollShadowTop.png │ │ ├── ScrollShadowTop_Left.png │ │ ├── ScrollShadowTop_Right.png │ │ ├── ScrollbarHandle.png │ │ ├── ScrollbarHandle_Bottom.png │ │ ├── ScrollbarHandle_Top.png │ │ ├── Selectbox.png │ │ ├── SelectboxActive.png │ │ ├── SelectboxActive_Left.png │ │ ├── SelectboxOpen_Right.png │ │ ├── Selectbox_Left.png │ │ ├── Selectbox_Right.png │ │ ├── SelectdropDivider.png │ │ ├── Selectdrop_BL.png │ │ ├── Selectdrop_BR.png │ │ ├── Selectdrop_Bottom.png │ │ ├── Selectdrop_Left.png │ │ ├── Selectdrop_Mid.png │ │ ├── Selectdrop_Right.png │ │ ├── Selectdrop_TL.png │ │ ├── Selectdrop_TR.png │ │ ├── Selectdrop_Top.png │ │ ├── SliderBg.png │ │ ├── SliderBgFill.png │ │ ├── SliderBgFill_Left.png │ │ ├── SliderBg_Left.png │ │ ├── SliderBg_Right.png │ │ ├── SliderKnob.png │ │ ├── SunkenFrame_BL.png │ │ ├── SunkenFrame_BR.png │ │ ├── SunkenFrame_Bottom.png │ │ ├── SunkenFrame_Left.png │ │ ├── SunkenFrame_Mid.png │ │ ├── SunkenFrame_Right.png │ │ ├── SunkenFrame_TL.png │ │ ├── SunkenFrame_TR.png │ │ ├── SunkenFrame_Top.png │ │ ├── atlas.png │ │ ├── atlas.txt │ │ └── blank.png └── __init__.py ├── Tests ├── Test.py ├── Test_Performance.py ├── Unittests.py └── common.py ├── config.ini ├── source ├── config_lui.cxx ├── config_lui.h ├── luiAtlas.I ├── luiAtlas.cxx ├── luiAtlas.h ├── luiAtlasDescriptor.I ├── luiAtlasDescriptor.cxx ├── luiAtlasDescriptor.h ├── luiAtlasPacker.cxx ├── luiAtlasPacker.h ├── luiAtlasPool.I ├── luiAtlasPool.cxx ├── luiAtlasPool.h ├── luiBaseElement.I ├── luiBaseElement.cxx ├── luiBaseElement.h ├── luiBaseLayout.I ├── luiBaseLayout.cxx ├── luiBaseLayout.h ├── luiBounds.I ├── luiBounds.cxx ├── luiBounds.h ├── luiChunkDescriptor.I ├── luiChunkDescriptor.cxx ├── luiChunkDescriptor.h ├── luiColorable.I ├── luiColorable.cxx ├── luiColorable.h ├── luiEventData.I ├── luiEventData.cxx ├── luiEventData.h ├── luiExpression.I ├── luiExpression.cxx ├── luiExpression.h ├── luiFontPool.I ├── luiFontPool.cxx ├── luiFontPool.h ├── luiHorizontalLayout.cxx ├── luiHorizontalLayout.h ├── luiInputHandler.I ├── luiInputHandler.cxx ├── luiInputHandler.h ├── luiIterators.h ├── luiObject.I ├── luiObject.cxx ├── luiObject.h ├── luiRect.I ├── luiRect.cxx ├── luiRect.h ├── luiRegion.I ├── luiRegion.cxx ├── luiRegion.h ├── luiRoot.I ├── luiRoot.cxx ├── luiRoot.h ├── luiSprite.I ├── luiSprite.cxx ├── luiSprite.h ├── luiText.I ├── luiText.cxx ├── luiText.h ├── luiVertexChunk.I ├── luiVertexChunk.cxx ├── luiVertexChunk.h ├── luiVertexData.h ├── luiVertexPool.I ├── luiVertexPool.cxx ├── luiVertexPool.h ├── luiVerticalLayout.cxx └── luiVerticalLayout.h └── update_module_builder.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Prefab gitignore which can be used by the user to ignore the files generated 3 | # by the module builder 4 | 5 | *.pyd 6 | *.pyc 7 | *.so 8 | *.pdb 9 | 10 | # Various output names 11 | win_*/ 12 | linux_*/ 13 | source/interrogate* 14 | 15 | # Source and script files 16 | scripts/ 17 | CMakeLists.txt 18 | build.py 19 | LICENSE 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | sudo: required 3 | dist: trusty 4 | compiler: gcc 5 | addons: 6 | apt: 7 | sources: 8 | - sourceline: "deb http://archive.panda3d.org/ubuntu/ trusty-dev main" 9 | packages: 10 | - cmake 11 | - libeigen3-dev 12 | - libfreetype6-dev 13 | - panda3d1.10 14 | 15 | script: 16 | - export PYTHONPATH=${PYTHONPATH}:/usr/lib/python2.7/dist-packages 17 | - export PYTHONPATH=${PYTHONPATH}:/usr/share/panda3d 18 | - python2.7 update_module_builder.py 19 | - python2.7 build.py 20 | - python2.7 -c "import panda3d; import lui; print(dir(lui))" 21 | -------------------------------------------------------------------------------- /Builtin/LUIButton.py: -------------------------------------------------------------------------------- 1 | 2 | from LUIObject import LUIObject 3 | from LUILayouts import LUIHorizontalStretchedLayout 4 | from LUILabel import LUILabel 5 | from LUIInitialState import LUIInitialState 6 | 7 | __all__ = ["LUIButton"] 8 | 9 | 10 | class LUIButton(LUIObject): 11 | 12 | """ Simple button, containing three sprites and a label. """ 13 | 14 | def __init__(self, text="Button", template="ButtonDefault", **kwargs): 15 | """ Constructs a new button. The template controls which sprites to use. 16 | If the template is "ButtonDefault" for example, the sprites 17 | "ButtonDefault_Left", "ButtonDefault" and "ButtonDefault_Right" will 18 | be used. The sprites used when the button is pressed should be named 19 | "ButtonDefaultFocus_Left" and so on then. 20 | 21 | If an explicit width is set on the button, the button will stick to 22 | that width, otherwise it will automatically resize to fit the label """ 23 | LUIObject.__init__(self, x=0, y=0, solid=True) 24 | self._template = template 25 | self._layout = LUIHorizontalStretchedLayout( 26 | parent=self, prefix=self._template, width="100%") 27 | self._label = LUILabel(parent=self, text=text) 28 | self._label.z_offset = 1 29 | self._label.center_vertical = True 30 | self._label.margin = 0, 20, 0, 20 31 | self.margin.left = -1 32 | LUIInitialState.init(self, kwargs) 33 | 34 | @property 35 | def text(self): 36 | """ Returns the current label text of the button """ 37 | return self._label.text 38 | 39 | @text.setter 40 | def text(self, text): 41 | """ Sets the label text of the button """ 42 | self._label.text = text 43 | 44 | def on_mousedown(self, event): 45 | """ Internal on_mousedown handler. Do not override """ 46 | self._layout.prefix = self._template + "Focus" 47 | self._label.margin.top = 1 48 | 49 | def on_mouseup(self, event): 50 | """ Internal on_mouseup handler. Do not override """ 51 | self._layout.prefix = self._template 52 | self._label.margin.top = 0 53 | -------------------------------------------------------------------------------- /Builtin/LUICheckbox.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | 4 | from LUIObject import LUIObject 5 | from LUISprite import LUISprite 6 | from LUILabel import LUILabel 7 | from LUIInitialState import LUIInitialState 8 | 9 | __all__ = ["LUICheckbox"] 10 | 11 | 12 | class LUICheckbox(LUIObject): 13 | 14 | """ This is a simple checkbox, including a Label. The checkbox can either 15 | be checked or unchecked. """ 16 | 17 | def __init__(self, checked=False, label=u"Checkbox", **kwargs): 18 | """ Constructs a new checkbox with the given label and state. By default, 19 | the checkbox is not checked. """ 20 | LUIObject.__init__(self, x=0, y=0, solid=True) 21 | self._checked = checked 22 | self._checkbox_sprite = LUISprite(self, "Checkbox_Default", "skin") 23 | self._label = LUILabel(parent=self, text=label, margin=(0, 0, 0, 25), 24 | center_vertical=True, alpha=0.4) 25 | self._hovered = False 26 | self._update_sprite() 27 | LUIInitialState.init(self, kwargs) 28 | 29 | @property 30 | def checked(self): 31 | """ Returns True if the checkbox is currently checked """ 32 | return self._checked 33 | 34 | @checked.setter 35 | def checked(self, checked): 36 | """ Sets the checkbox state """ 37 | self._checked = checked 38 | self._update_sprite() 39 | 40 | def toggle(self): 41 | """ Toggles the checkbox state """ 42 | self.checked = not self.checked 43 | 44 | @property 45 | def label(self): 46 | """ Returns a handle to the label, so it can be modified """ 47 | return self._label 48 | 49 | @property 50 | def sprite(self): 51 | """ Returns a handle to the internal checkbox sprite """ 52 | return self._checkbox_sprite 53 | 54 | def on_click(self, event): 55 | """ Internal onclick handler. Do not override """ 56 | self._checked = not self._checked 57 | self.trigger_event("changed") 58 | self._update_sprite() 59 | 60 | def on_mousedown(self, event): 61 | """ Internal mousedown handler. """ 62 | self._checkbox_sprite.color = (0.9, 0.9, 0.9, 1.0) 63 | 64 | def on_mouseup(self, event): 65 | """ Internal on_mouseup handler. """ 66 | self._checkbox_sprite.color = (1, 1, 1, 1) 67 | 68 | def on_mouseover(self, event): 69 | """ Internal mouseover handler """ 70 | self._hovered = True 71 | self._update_sprite() 72 | 73 | def on_mouseout(self, event): 74 | """ Internal mouseout handler """ 75 | self._hovered = False 76 | self._update_sprite() 77 | 78 | def _update_sprite(self): 79 | """ Internal method to update the sprites """ 80 | img = "Checkbox_Checked" if self._checked else "Checkbox_Default" 81 | if self._hovered: 82 | img += "Hover" 83 | self._checkbox_sprite.set_texture(img, "skin") 84 | -------------------------------------------------------------------------------- /Builtin/LUIFormattedLabel.py: -------------------------------------------------------------------------------- 1 | 2 | from panda3d.core import LVecBase2i 3 | from LUIObject import LUIObject 4 | from LUILabel import LUILabel 5 | from LUIInitialState import LUIInitialState 6 | 7 | __all__ = ["LUIFormattedLabel"] 8 | 9 | 10 | class LUIFormattedLabel(LUIObject): 11 | 12 | """ Small helper class to build a text consisting of different formatted 13 | parts of text. Uses LUILabels internally """ 14 | 15 | def __init__(self, **kwargs): 16 | """ Creates a new formatted label. """ 17 | LUIObject.__init__(self) 18 | LUIInitialState.init(self, kwargs) 19 | self._cursor = LVecBase2i(0) 20 | self._last_size = 14 21 | 22 | def clear(self): 23 | """ Removes all text from this label and resets it to the initial state. 24 | This will also detach the sub-labels from this label. """ 25 | self._cursor.set(0, 0) 26 | self.remove_all_children() 27 | 28 | def newline(self, font_size=None): 29 | """ Moves the cursor to the next line. The font size controls how much 30 | the cursor will move. By default, the font size of the last added text 31 | is used, or if no text was added yet, a size of 14.""" 32 | self._cursor.x = 0 33 | if font_size is None: 34 | font_size = self._last_size 35 | self._cursor.y += font_size + 2 36 | 37 | def add(self, *args, **kwargs): 38 | """ Appends a new text. The arguments are equal to the arguments of 39 | LUILabel. The arguments shouldn't contain information about the 40 | placement like top_left, or center_vertical, since the labels are 41 | placed at explicit positions. """ 42 | self._last_size = kwargs.get("font_size", 14) 43 | label = LUILabel(parent=self, left=self._cursor.x, top=self._cursor.y, 44 | *args, **kwargs) 45 | # This is a bit of a hack, we should use a horizontal layout, but we 46 | # don't for performance reasons. 47 | self._cursor.x += label.text_handle.width 48 | -------------------------------------------------------------------------------- /Builtin/LUIFrame.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import print_function 3 | 4 | from LUIObject import LUIObject 5 | from LUISprite import LUISprite 6 | from LUILayouts import LUICornerLayout 7 | from LUIInitialState import LUIInitialState 8 | from LUIScrollableRegion import LUIScrollableRegion 9 | 10 | __all__ = ["LUIFrame"] 11 | 12 | 13 | class LUIFrame(LUIObject): 14 | 15 | """ A container which can store multiple ui-elements. If you don't want a 16 | border/background, you should use an empty LUIObject as container instead. 17 | """ 18 | 19 | FS_sunken = 1 20 | FS_raised = 2 21 | 22 | def __init__(self, inner_padding=5, scrollable=False, style=FS_raised, 23 | **kwargs): 24 | """ Creates a new frame with the given options and style. If scrollable 25 | is True, the contents of the frame will scroll if they don't fit into 26 | the frame height. inner_padding only has effect if scrollable is True. 27 | You can call fit_to_children() to make the frame fit automatically to 28 | it's contents.""" 29 | LUIObject.__init__(self) 30 | 31 | # Each *style* has a different border size (size of the shadow). The 32 | # border size shouldn't get calculated to the actual framesize, so we 33 | # are determining it first and then substracting it. 34 | # TODO: We could do this automatically, determined by the sprite size 35 | # probably? 36 | self._border_size = 0 37 | self.padding = 10 38 | self.solid = True 39 | prefix = "" 40 | 41 | if style == LUIFrame.FS_raised: 42 | temp = LUISprite(self, "Frame_Left", "skin") 43 | self._border_size = temp.width 44 | self.remove_child(temp) 45 | prefix = "Frame_" 46 | elif style == LUIFrame.FS_sunken: 47 | self._border_size = 0 48 | prefix = "SunkenFrame_" 49 | else: 50 | raise Exception("Unkown LUIFrame style: " + style) 51 | 52 | self._scrollable = scrollable 53 | self._layout = LUICornerLayout(parent=self, image_prefix=prefix) 54 | self._layout.margin = -(self.padding.top + self._border_size) 55 | if self._scrollable: 56 | self._content = LUIObject(self) 57 | self._content.size = (self.width, self.height) 58 | self._content.pos = (self._border_size, self._border_size) 59 | self._scroll_content = LUIScrollableRegion( 60 | self._content, 61 | width=self.width - 2 * self.padding.left, 62 | height=self.height - 2 * self.padding.left, 63 | padding=inner_padding) 64 | self.content_node = self._scroll_content.content_node 65 | 66 | LUIInitialState.init(self, kwargs) 67 | -------------------------------------------------------------------------------- /Builtin/LUIHorizontalLayout.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUIHorizontalLayout as _LUIHorizontalLayout 8 | from LUIInitialState import LUIInitialState 9 | 10 | __all__ = ["LUIHorizontalLayout"] 11 | 12 | 13 | class LUIHorizontalLayout(_LUIHorizontalLayout): 14 | """ This is a wrapper class for the C++ LUIHorizontalLayout class, to be 15 | able to use it in a more convenient way. It leverages LUIInitialState 16 | to be able to pass arbitrary keyword arguments. """ 17 | 18 | def __init__(self, parent=None, spacing=0.0, **kwargs): 19 | _LUIHorizontalLayout.__init__(self, parent, spacing) 20 | LUIInitialState.init(self, kwargs) 21 | -------------------------------------------------------------------------------- /Builtin/LUIInitialState.py: -------------------------------------------------------------------------------- 1 | 2 | __all__ = ["LUIInitialState"] 3 | 4 | 5 | class LUIInitialState: 6 | 7 | """ Small helper class to pass keyword arguments to the LUI-objects. It takes 8 | all keyword arguments of a given call, and calls obj. = for 9 | each keyword. It usually is called at the end of the __init__ method. """ 10 | 11 | def __init__(self): 12 | raise Exception("LUIInitialState is a static class") 13 | 14 | # Some properties have alternative names, under which they can be accessed. 15 | __MAPPINGS = { 16 | "x": "left", 17 | "y": "top", 18 | "w": "width", 19 | "h": "height" 20 | } 21 | 22 | @classmethod 23 | def init(cls, obj, kwargs): 24 | """ Applies all keyword arguments as properties. For example, passing 25 | dict({"left": 10, "top": 3, "color": (0.2, 0.6, 1.0)}) results in 26 | behaviour similar to: 27 | 28 | element.left = 10 29 | element.top = 3 30 | element.color = 0.2, 0.6, 1.0 31 | 32 | Calling this method allows setting arbitrary properties in 33 | constructors, without having to specify each possible keyword argument. 34 | """ 35 | for arg_name, arg_val in kwargs.items(): 36 | arg_name = cls.__MAPPINGS.get(arg_name, arg_name) 37 | if hasattr(obj, arg_name): 38 | setattr(obj, arg_name, arg_val) 39 | else: 40 | raise AttributeError("{0} has no attribute {1}".format( 41 | obj.__class__.__name__, arg_name)) 42 | -------------------------------------------------------------------------------- /Builtin/LUIInputHandler.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUIInputHandler as __LUIInputHandler 8 | LUIInputHandler = __LUIInputHandler 9 | -------------------------------------------------------------------------------- /Builtin/LUILabel.py: -------------------------------------------------------------------------------- 1 | 2 | from panda3d.lui import LUIText 3 | from LUIObject import LUIObject 4 | from LUIInitialState import LUIInitialState 5 | 6 | __all__ = ["LUILabel"] 7 | 8 | class LUILabel(LUIObject): 9 | 10 | """ A simple label, displaying text. """ 11 | 12 | # Default variables which can be overridden by skins 13 | DEFAULT_COLOR = (0.9, 0.9, 0.9, 1) 14 | DEFAULT_USE_SHADOW = True 15 | 16 | def __init__(self, text="Label", shadow=None, font_size=14, font="label", color=None, wordwrap=False, **kwargs): 17 | """ Creates a new label. If shadow is True, a small text shadow will be 18 | rendered below the actual text. """ 19 | LUIObject.__init__(self) 20 | LUIInitialState.init(self, kwargs) 21 | self._text = LUIText( 22 | self, 23 | text, 24 | font, 25 | font_size, 26 | 0, 27 | 0, 28 | wordwrap 29 | ) 30 | self._text.z_offset = 1 31 | if color is None: 32 | self.color = LUILabel.DEFAULT_COLOR 33 | else: 34 | self.color = color 35 | if shadow is None: 36 | shadow = LUILabel.DEFAULT_USE_SHADOW 37 | self._have_shadow = shadow 38 | if self._have_shadow: 39 | self._shadow_text = LUIText( 40 | self, 41 | text, 42 | font, 43 | font_size, 44 | 0, 45 | 0, 46 | wordwrap 47 | ) 48 | self._shadow_text.top = 1 49 | self._shadow_text.color = (0,0,0,0.6) 50 | 51 | def get_text_handle(self): 52 | """ Returns a handle to the internal used LUIText object """ 53 | return self._text 54 | 55 | text_handle = property(get_text_handle) 56 | 57 | def get_text(self): 58 | """ Returns the current text of the label """ 59 | return self._text.text 60 | 61 | def set_text(self, text): 62 | """ Sets the text of the label """ 63 | self._text.text = text 64 | if self._have_shadow: 65 | self._shadow_text.text = text 66 | 67 | text = property(get_text, set_text) 68 | 69 | def get_color(self): 70 | """ Returns the current color of the label's text """ 71 | return self._text.color 72 | 73 | def set_color(self, color): 74 | """ Sets the color of the label's text """ 75 | self._text.color = color 76 | 77 | color = property(get_color, set_color) 78 | -------------------------------------------------------------------------------- /Builtin/LUIObject.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUIObject as _LUIObject 8 | from LUIInitialState import LUIInitialState 9 | 10 | __all__ = ["LUIObject"] 11 | 12 | class LUIObject(_LUIObject): 13 | """ This is a wrapper class for the C++ LUIObject class, to be able to 14 | use it in a more convenient way """ 15 | 16 | def __init__(self, *args, **kwargs): 17 | _LUIObject.__init__(self, *args) 18 | LUIInitialState.init(self, kwargs) 19 | -------------------------------------------------------------------------------- /Builtin/LUIProgressbar.py: -------------------------------------------------------------------------------- 1 | 2 | from LUIObject import LUIObject 3 | from LUISprite import LUISprite 4 | 5 | from LUILayouts import LUIHorizontalStretchedLayout 6 | from LUILabel import LUILabel 7 | 8 | class LUIProgressbar(LUIObject): 9 | 10 | """ A simple progress bar """ 11 | 12 | def __init__(self, parent=None, width=200, value=50, show_label=True): 13 | """ Constructs a new progress bar. If show_label is True, a label indicating 14 | the current progress is shown """ 15 | LUIObject.__init__(self) 16 | self.set_width(width) 17 | 18 | self._bg_layout = LUIHorizontalStretchedLayout( 19 | parent=self, prefix="ProgressbarBg", width="100%") 20 | 21 | self._fg_left = LUISprite(self, "ProgressbarFg_Left", "skin") 22 | self._fg_mid = LUISprite(self, "ProgressbarFg", "skin") 23 | self._fg_right = LUISprite(self, "ProgressbarFg_Right", "skin") 24 | self._fg_finish = LUISprite(self, "ProgressbarFg_Finish", "skin") 25 | 26 | self._show_label = show_label 27 | self._progress_pixel = 0 28 | self._fg_finish.right = 0 29 | 30 | if self._show_label: 31 | self._progress_label = LUILabel(parent=self, text=u"33 %") 32 | self._progress_label.centered = (True, True) 33 | 34 | self.set_value(value) 35 | self._update_progress() 36 | 37 | if parent is not None: 38 | self.parent = parent 39 | 40 | def get_value(self): 41 | """ Returns the current value of the progress bar """ 42 | return (self._progress_pixel / self.width * 100.0) 43 | 44 | def set_value(self, val): 45 | """ Sets the value of the progress bar """ 46 | val = max(0, min(100, val)) 47 | self._progress_pixel = int(val / 100.0 * self.width) 48 | self._update_progress() 49 | 50 | value = property(get_value, set_value) 51 | 52 | def _update_progress(self): 53 | """ Internal method to update the progressbar """ 54 | self._fg_finish.hide() 55 | 56 | if self._progress_pixel <= self._fg_left.width + self._fg_right.width: 57 | self._fg_mid.hide() 58 | self._fg_right.left = self._fg_left.width 59 | else: 60 | self._fg_mid.show() 61 | self._fg_mid.left = self._fg_left.width 62 | self._fg_mid.width = self._progress_pixel - self._fg_right.width - self._fg_left.width 63 | self._fg_right.left = self._fg_mid.left + self._fg_mid.width 64 | 65 | if self._progress_pixel >= self.width - self._fg_right.width: 66 | self._fg_finish.show() 67 | self._fg_finish.right = - (self.width - self._progress_pixel) 68 | self._fg_finish.clip_bounds = (0, self.width - self._progress_pixel, 0, 0) 69 | 70 | if self._show_label: 71 | percentage = self._progress_pixel / self.width * 100.0 72 | self._progress_label.set_text("{} %".format(int(percentage))) 73 | -------------------------------------------------------------------------------- /Builtin/LUIRadiobox.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division 3 | 4 | from LUIObject import LUIObject 5 | from LUISprite import LUISprite 6 | from LUIInitialState import LUIInitialState 7 | from LUILabel import LUILabel 8 | 9 | class LUIRadiobox(LUIObject): 10 | 11 | """ A radiobox which can be used in combination with a LUIRadioboxGroup """ 12 | 13 | def __init__(self, parent=None, group=None, value=None, active=False, label=u"Radiobox", **kwargs): 14 | """ Constructs a new radiobox. group should be a handle to a LUIRadioboxGroup. 15 | value will be the value returned by group.value, in case the box was 16 | selected. By default, the radiobox is not active. """ 17 | assert group is not None, "LUIRadiobox needs a LUIRadioboxGroup!" 18 | LUIObject.__init__(self, x=0, y=0, solid=True) 19 | self._sprite = LUISprite(self, "Radiobox_Default", "skin") 20 | self._label = LUILabel(parent=self, text=label, margin=(0, 0, 0, 23), 21 | center_vertical=True) 22 | self._value = value 23 | self._active = False 24 | self._hovered = False 25 | self._group = group 26 | self._group.register_box(self) 27 | if active: 28 | self.set_active() 29 | if parent: 30 | self.parent = parent 31 | LUIInitialState.init(self, kwargs) 32 | 33 | def on_click(self, event): 34 | """ Internal onclick handler. Do not override. """ 35 | self.set_active() 36 | 37 | def on_mouseover(self, event): 38 | """ Internal mouseover handler """ 39 | self._hovered = True 40 | self._update_sprite() 41 | 42 | def on_mouseout(self, event): 43 | """ Internal mouseout handler """ 44 | self._hovered = False 45 | self._update_sprite() 46 | 47 | def set_active(self): 48 | """ Internal function to set the radiobox active """ 49 | if self._group is not None: 50 | self._group.set_active_box(self) 51 | else: 52 | self._update_state(True) 53 | 54 | def get_value(self): 55 | """ Returns the value of the radiobox """ 56 | return self._value 57 | 58 | def set_value(self, value): 59 | """ Sets the value of the radiobox """ 60 | self._value = value 61 | 62 | value = property(get_value, set_value) 63 | 64 | def get_label(self): 65 | """ Returns a handle to the label, so it can be modified (e.g. change 66 | its text) """ 67 | return self._label 68 | 69 | label = property(get_label) 70 | 71 | def _update_state(self, active): 72 | """ Internal method to update the state of the radiobox. Called by the 73 | LUIRadioboxGroup """ 74 | self._active = active 75 | self.trigger_event("changed") 76 | self._update_sprite() 77 | 78 | def on_mousedown(self, event): 79 | """ Internal onmousedown handler. Do not override. """ 80 | self._sprite.color = (0.86,0.86,0.86,1.0) 81 | 82 | def on_mouseup(self, event): 83 | """ Internal onmouseup handler. Do not override. """ 84 | self._sprite.color = (1,1,1,1) 85 | 86 | def _update_sprite(self): 87 | """ Internal function to update the sprite of the radiobox """ 88 | img = "Radiobox_Active" if self._active else "Radiobox_Default" 89 | if self._hovered: 90 | img += "Hover" 91 | self._sprite.set_texture(img, "skin") 92 | -------------------------------------------------------------------------------- /Builtin/LUIRadioboxGroup.py: -------------------------------------------------------------------------------- 1 | 2 | from LUIObject import LUIObject 3 | 4 | class LUIRadioboxGroup(LUIObject): 5 | 6 | """ Simple helper to group a bunch of LUIRadiobox and ensure only one is 7 | checked at one timem """ 8 | 9 | def __init__(self): 10 | """ Constructs a new group without any radioboxes inside """ 11 | self._boxes = [] 12 | self._selected_box = None 13 | 14 | def register_box(self, box): 15 | """ Registers a box to the collection """ 16 | if box not in self._boxes: 17 | self._boxes.append(box) 18 | 19 | def set_active_box(self, active_box): 20 | """ Internal function to set the active box """ 21 | for box in self._boxes: 22 | if box is not active_box: 23 | box._update_state(False) 24 | else: 25 | box._update_state(True) 26 | self._selected_box = active_box 27 | 28 | def get_active_box(self): 29 | """ Returns the current selected box """ 30 | return self._selected_box 31 | 32 | active_box = property(get_active_box, set_active_box) 33 | 34 | def get_active_value(self): 35 | """ Returns the value of the current selected box (or None if none is 36 | selected) """ 37 | if self._selected_box is None: 38 | return None 39 | return self._selected_box.get_value() 40 | 41 | active_value = property(get_active_value) 42 | -------------------------------------------------------------------------------- /Builtin/LUIRegion.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUIRegion as __LUIRegion 8 | LUIRegion = __LUIRegion 9 | -------------------------------------------------------------------------------- /Builtin/LUIRoot.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUIRoot as __LUIRoot 8 | LUIRoot = __LUIRoot 9 | -------------------------------------------------------------------------------- /Builtin/LUISkin.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from os.path import join 4 | 5 | from panda3d.core import Filename 6 | from panda3d.lui import LUIFontPool, LUIAtlasPool 7 | 8 | class LUISkin: 9 | 10 | """ Abstract class, each skin derives from this class """ 11 | 12 | skin_location = "" 13 | 14 | def __init__(self): 15 | pass 16 | 17 | def load(self): 18 | """ Skins should override this. Each skin should at least provide the fonts 19 | 'default' and 'label', and at least one atlas named 'skin' """ 20 | raise NotImplementedError() 21 | 22 | def get_resource(self, pth): 23 | """ Turns a relative path into an absolute one, using the skin_location """ 24 | return Filename.from_os_specific(join(self.skin_location, pth)).get_fullpath() 25 | 26 | 27 | class LUIDefaultSkin(LUISkin): 28 | 29 | """ The default skin which comes with LUI """ 30 | 31 | skin_location = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../Skins/Default/") 32 | 33 | def __init__(self): 34 | pass 35 | 36 | def load(self): 37 | LUIFontPool.get_global_ptr().register_font( 38 | "default", loader.loadFont(self.get_resource("font/SourceSansPro-Semibold.ttf"))) 39 | 40 | labelFont = loader.loadFont(self.get_resource("font/SourceSansPro-Semibold.ttf")) 41 | labelFont.setPixelsPerUnit(32) 42 | 43 | LUIFontPool.get_global_ptr().register_font( 44 | "label", labelFont) 45 | 46 | headerFont = loader.loadFont(self.get_resource("font/SourceSansPro-Light.ttf")) 47 | headerFont.setPixelsPerUnit(80) 48 | 49 | LUIFontPool.get_global_ptr().register_font("header", headerFont) 50 | 51 | LUIAtlasPool.get_global_ptr().load_atlas("skin", 52 | self.get_resource("res/atlas.txt"), 53 | self.get_resource("res/atlas.png")) 54 | -------------------------------------------------------------------------------- /Builtin/LUISprite.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUISprite as _LUISprite 8 | from LUIInitialState import LUIInitialState 9 | 10 | __all__ = ["LUISprite"] 11 | 12 | class LUISprite(_LUISprite): 13 | """ This is a wrapper class for the C++ LUISprite class, to be able to 14 | use it in a more convenient way """ 15 | 16 | def __init__(self, *args, **kwargs): 17 | _LUISprite.__init__(self, *args) 18 | LUIInitialState.init(self, kwargs) 19 | -------------------------------------------------------------------------------- /Builtin/LUISpriteButton.py: -------------------------------------------------------------------------------- 1 | 2 | from LUIObject import LUIObject 3 | from LUISprite import LUISprite 4 | from LUIInitialState import LUIInitialState 5 | 6 | class LUISpriteButton(LUIObject): 7 | 8 | """ Simple button that uses only two images: Default and focus. """ 9 | 10 | def __init__(self, template="ButtonDefault", **kwargs): 11 | LUIObject.__init__(self, x=0, y=0, solid=True) 12 | self._template = template 13 | self._button_sprite = LUISprite(self, template, "skin") 14 | if 'width' in kwargs: 15 | self._button_sprite.width = kwargs['width'] 16 | if 'height' in kwargs: 17 | self._button_sprite.height = kwargs['height'] 18 | LUIInitialState.init(self, kwargs) 19 | 20 | def on_mousedown(self, event): 21 | """ Internal on_mousedown handler. Do not override """ 22 | self._button_sprite.set_texture(self.template + "Focus", "skin", resize=False) 23 | 24 | def on_mouseup(self, event): 25 | """ Internal on_mouseup handler. Do not override """ 26 | self._button_sprite.set_texture(self.template, "skin", resize=False) 27 | 28 | def on_click(self, event): 29 | """ Internal onclick handler. Do not override """ 30 | self.trigger_event("changed") 31 | -------------------------------------------------------------------------------- /Builtin/LUIVerticalLayout.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This is a wrapper file. It contains no actual implementation 4 | 5 | """ 6 | 7 | from panda3d.lui import LUIVerticalLayout as _LUIVerticalLayout 8 | from LUIInitialState import LUIInitialState 9 | 10 | __all__ = ["LUIVerticalLayout"] 11 | 12 | 13 | class LUIVerticalLayout(_LUIVerticalLayout): 14 | """ This is a wrapper class for the C++ LUIVerticalLayout class, to be 15 | able to use it in a more convenient way. It leverages LUIInitialState 16 | to be able to pass arbitrary keyword arguments. """ 17 | 18 | def __init__(self, parent=None, spacing=0.0, **kwargs): 19 | _LUIVerticalLayout.__init__(self, parent, spacing) 20 | LUIInitialState.init(self, kwargs) 21 | -------------------------------------------------------------------------------- /Builtin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Builtin/__init__.py -------------------------------------------------------------------------------- /Demos/.gitignore: -------------------------------------------------------------------------------- 1 | Test.py 2 | -------------------------------------------------------------------------------- /Demos/01_MinimalExample.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This file shows the smallest working LUI example, on which you can base your 4 | LUI projects. 5 | 6 | """ 7 | 8 | # Add lui modules to the path. This will not be required when LUI is included 9 | # in panda. 10 | import sys 11 | sys.path.insert(0, "../Builtin") 12 | 13 | # Load some builtin LUI classes. When lui is included in panda, this will be 14 | # from direct.lui.LUIButton import LUIButton 15 | from LUIButton import LUIButton 16 | from LUISkin import LUIDefaultSkin 17 | from LUIRegion import LUIRegion 18 | from LUIInputHandler import LUIInputHandler 19 | 20 | # Setup panda, nothing special here 21 | from panda3d.core import load_prc_file_data 22 | load_prc_file_data("", """ 23 | text-minfilter linear 24 | text-magfilter linear 25 | text-pixels-per-unit 32 26 | sync-video #f 27 | textures-power-2 none 28 | show-frame-rate-meter #t 29 | win-size 700 600 30 | window-title LUI Minimal Example 31 | """) 32 | 33 | from direct.showbase.ShowBase import ShowBase 34 | 35 | class Application(ShowBase): 36 | 37 | def __init__(self): 38 | ShowBase.__init__(self) 39 | 40 | # Construct a new LUIRegion 41 | region = LUIRegion.make("LUI", base.win) 42 | 43 | # Construct a new InputHandler to catch and process events 44 | handler = LUIInputHandler() 45 | base.mouseWatcher.attach_new_node(handler) 46 | region.set_input_handler(handler) 47 | 48 | # Load the default LUI skin 49 | skin = LUIDefaultSkin() 50 | skin.load() 51 | 52 | # LUI is initialized now, so we can start adding elements, for example: 53 | button = LUIButton(parent=region.root, text="Hello world!", top=30, left=30) 54 | 55 | Application().run() 56 | -------------------------------------------------------------------------------- /Demos/02_SimpleConsole.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import sys 3 | sys.path.insert(0, "../Builtin") 4 | sys.path.insert(0, "../") 5 | 6 | from direct.showbase.ShowBase import ShowBase 7 | from direct.showbase.DirectObject import DirectObject 8 | 9 | from panda3d.core import * 10 | load_prc_file_data("", """ 11 | notify-level-lui info 12 | text-minfilter linear 13 | text-magfilter linear 14 | text-pixels-per-unit 32 15 | sync-video #f 16 | textures-power-2 none 17 | show-frame-rate-meter #t 18 | win-size 780 630 19 | window-title LUI Demo 20 | win-fixed-size #f 21 | """) 22 | 23 | # Imports 24 | 25 | import codecs 26 | 27 | from LUISkin import LUIDefaultSkin 28 | from LUIFrame import LUIFrame 29 | from LUILabel import LUILabel 30 | from LUIInputField import LUIInputField 31 | from LUIFormattedLabel import LUIFormattedLabel 32 | from LUIScrollableRegion import LUIScrollableRegion 33 | from LUIObject import LUIObject 34 | from LUIRegion import LUIRegion 35 | from LUIInputHandler import LUIInputHandler 36 | from LUIVerticalLayout import LUIVerticalLayout 37 | 38 | from Skins.Metro.LUIMetroSkin import LUIMetroSkin 39 | 40 | s = ShowBase() 41 | 42 | # Load a LUI Skin 43 | if False: 44 | skin = LUIMetroSkin() 45 | base.win.set_clear_color(Vec4(1)) 46 | else: 47 | skin = LUIDefaultSkin() 48 | base.win.set_clear_color(Vec4(0.1, 0.0, 0.0, 1)) 49 | 50 | skin.load() 51 | 52 | # Initialize LUI 53 | region = LUIRegion.make("LUI", base.win) 54 | handler = LUIInputHandler() 55 | base.mouseWatcher.attach_new_node(handler) 56 | region.set_input_handler(handler) 57 | 58 | # Title 59 | title_label = LUILabel(parent=region.root, text="LUI Console Example", font_size=40, 60 | font="header", pos=(25, 17)) 61 | 62 | # Container 63 | container = LUIFrame(parent = region.root, width=700, height=500, 64 | style=LUIFrame.FS_sunken, margin=30, top=50) 65 | 66 | text_container = LUIScrollableRegion(parent=container, width=675, height=440, 67 | padding=0) 68 | 69 | base.win.set_clear_color(Vec4(0.1, 0.1, 0.1, 1.0)) 70 | layout = LUIVerticalLayout(parent=text_container.content_node) 71 | 72 | def send_command(event): 73 | """ Called when the user presses enter in the input field, submits the 74 | command and prints something on the console """ 75 | label = LUIFormattedLabel() 76 | color = (0.9, 0.9, 0.9, 1.0) 77 | if event.message.startswith(u"/"): 78 | color = (0.35, 0.65, 0.24, 1.0) 79 | label.add(text=">>> ", color=(0.35, 0.65, 0.24, 1.0)) 80 | label.add(text=event.message, color=color) 81 | layout.add(label) 82 | 83 | result = LUIFormattedLabel() 84 | result.add("Your command in rot13: " + codecs.encode(event.message, "rot13"), color=(0.4, 0.4, 0.4, 1.0)) 85 | layout.add(result) 86 | input_field.clear() 87 | 88 | text_container.scroll_to_bottom() 89 | 90 | # Create the input box 91 | input_field = LUIInputField(parent=container, bottom=0, left=0, width="100%") 92 | input_field.bind("enter", send_command) 93 | input_field.request_focus() 94 | 95 | # Add some initial commands 96 | for demo_command in ["Hello world!", "This is a simple console", "You can type commands like this:", "/test"]: 97 | input_field.trigger_event("enter", demo_command) 98 | 99 | s.run() 100 | -------------------------------------------------------------------------------- /Demos/B_BlockText.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUILabel import LUILabel 5 | from LUIBlockText import LUIBlockText 6 | from LUIScrollableRegion import LUIScrollableRegion 7 | 8 | import random 9 | 10 | f = DemoFramework() 11 | f.prepare_demo("LUIBlockText") 12 | 13 | # Constructor 14 | 15 | f.add_constructor_parameter("text", "u'Label'") 16 | f.add_constructor_parameter("shadow", "True") 17 | f.add_constructor_parameter("font_size", "14") 18 | f.add_constructor_parameter("font", "'label'") 19 | 20 | # Functions 21 | f.add_public_function("clear", []) 22 | f.add_public_function("set_text", [("text", "string")]) 23 | f.add_public_function("set_wrap", [("wrap", "boolean")]) 24 | f.add_public_function("set_width", [("width", "integer")]) 25 | 26 | f.add_property("labels", "list") 27 | 28 | # Events 29 | f.construct_sourcecode("LUIBlockText") 30 | 31 | text_container = LUIScrollableRegion( 32 | parent=f.get_widget_node(), 33 | width=340, 34 | height=190, 35 | padding=0, 36 | ) 37 | 38 | #TODO: Support newline through charcode 10 39 | #TODO: If space causes next line, dont print it 40 | 41 | # Create a new label 42 | label = LUIBlockText(parent=text_container, width=310) 43 | 44 | # Paragraph with no line breaks 45 | label.add( 46 | text='''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada sit amet erat non gravida. Pellentesque sit amet cursus risus Sed egestas, nulla in tempor cursus, ante felis cursus magna, nec vehicula nisi nulla eu nulla.''', 47 | color=(0.9,0.9,.9), 48 | wordwrap=True, 49 | padding=5, 50 | ) 51 | 52 | 53 | # Paragraph with some linebreaks 54 | label.add( 55 | text='''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada sit amet erat non gravida. 56 | Pellentesque sit amet cursus risus Sed egestas, nulla in tempor cursus, ante felis cursus magna, nec vehicula nisi nulla eu nulla. 57 | Nulla sed pellentesque erat. Morbi facilisis at erat id auctor. Phasellus euismod facilisis sem, at molestie velit condimentum sit amet. 58 | 59 | Nulla posuere rhoncus aliquam.''', 60 | color=(0.9,0.9,.9), 61 | wordwrap=True, 62 | padding=5, 63 | ) 64 | 65 | # Paragraph with no spaces or linebreaks 66 | label.add( 67 | text='''Loremipsumolorsitamet,consecteturadipiscingelit.Sedmalesuadasitameteratnongravida.PellentesquesitametcursusrisusSedegestas,nullaintemporcursus,antefeliscursusmagna,necvehiculanisinullaeunulla.''', 68 | color=(0.9,0.9,.9), 69 | wordwrap=True, 70 | padding=5, 71 | ) 72 | 73 | def setWidth(width): 74 | label.set_width(width) 75 | text_container.on_element_added() 76 | 77 | def setWrap(wrap): 78 | label.set_wrap(wrap) 79 | text_container.on_element_added() 80 | 81 | 82 | f.set_actions({ 83 | "Set Random Text": lambda: label.set_text(str(random.randint(100, 10000))), 84 | "Set Random Color": lambda: label.set_color((random.random(), random.random(), random.random(), 1)), 85 | "Clear": lambda: label.clear(), 86 | "Smaller": lambda: setWidth(200), 87 | "Larger": lambda: setWidth(310), 88 | "Wrapping on": lambda: setWrap(True), 89 | "Wrapping off": lambda: setWrap(False), 90 | }) 91 | 92 | base.run() 93 | -------------------------------------------------------------------------------- /Demos/B_Button.py: -------------------------------------------------------------------------------- 1 | 2 | from DemoFramework import DemoFramework 3 | from LUIButton import LUIButton 4 | from LUIHorizontalLayout import LUIHorizontalLayout 5 | 6 | import random 7 | 8 | f = DemoFramework() 9 | f.prepare_demo("LUIButton") 10 | 11 | # Constructor 12 | f.add_constructor_parameter("text", "u'Button'") 13 | f.add_constructor_parameter("template", "'ButtonDefault'") 14 | 15 | # Functions 16 | f.add_public_function("set_text", [("text", "string")]) 17 | f.add_public_function("get_text", [], "string") 18 | f.add_property("text", "string") 19 | 20 | # Construct source code 21 | f.construct_sourcecode("LUIButton") 22 | 23 | # Create 2 new buttons, and store them in a vertical layout 24 | layout = LUIHorizontalLayout(parent=f.get_widget_node(), spacing=10) 25 | 26 | button1 = LUIButton(text="Do not click me") 27 | button2 = LUIButton(text="Instead click me", template="ButtonGreen") 28 | 29 | layout.add(button1) 30 | layout.add(button2) 31 | 32 | f.set_actions({ 33 | "Set Random Text": lambda: button1.set_text("Text: " + str(random.randint(100, 10000000))), 34 | }) 35 | 36 | run() 37 | -------------------------------------------------------------------------------- /Demos/B_Checkbox.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUICheckbox import LUICheckbox 5 | 6 | import random 7 | 8 | f = DemoFramework() 9 | f.prepare_demo("LUICheckbox") 10 | 11 | # Constructor 12 | f.add_constructor_parameter("checked", "False") 13 | f.add_constructor_parameter("label", "'Checkbox'") 14 | 15 | # Functions 16 | f.add_public_function("get_checked", [], "bool") 17 | f.add_public_function("toggle_checked", [], "bool") 18 | f.add_public_function("set_checked", [("checked", "bool")]) 19 | f.add_public_function("get_label", [], "UILabel") 20 | 21 | f.add_property("checked", "bool") 22 | f.add_property("label", "LUILabel") 23 | 24 | # Events 25 | f.add_event("changed") 26 | f.construct_sourcecode("LUICheckbox") 27 | 28 | # Create the checkbox 29 | checkbox = LUICheckbox(parent=f.get_widget_node()) 30 | 31 | f.set_actions({ 32 | "Set Checked": lambda: checkbox.set_checked(True), 33 | "Set Unchecked": lambda: checkbox.set_checked(False), 34 | "Toggle Checked": lambda: checkbox.toggle_checked(), 35 | "Set Random Text": lambda: checkbox.get_label().set_text("Text: " + str(random.randint(100, 10000))), 36 | }) 37 | 38 | run() 39 | -------------------------------------------------------------------------------- /Demos/B_FormattedLabel.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUIFormattedLabel import LUIFormattedLabel 5 | 6 | import random 7 | 8 | f = DemoFramework() 9 | f.prepare_demo("LUIFormattedLabel") 10 | 11 | # Functions 12 | f.add_public_function("clear", [], "void") 13 | f.add_public_function("newline", [], "void") 14 | f.add_public_function("add", [("*args", "List"), ("**kwargs", "Dict")]) 15 | 16 | # Events 17 | f.construct_sourcecode("LUIFormattedLabel") 18 | 19 | # Create a new label 20 | label = LUIFormattedLabel(parent=f.get_widget_node()) 21 | 22 | # Add parts to the label 23 | label.add(text="Hello ", color=(0.2,0.6,1.0)) 24 | label.add(text="World", color=(1.0,0.6,0.2)) 25 | label.add(text="! ") 26 | label.add(text="This ", font_size=20, margin=(-6, 0, 0, 0), color=(0.4,0.2,1.0)) 27 | label.add(text="is ", color=(1.0,0.2,1.0)) 28 | label.add(text="a formatted ", font_size=10, color=(0.6,0.3,0.6)) 29 | label.add(text="Label", font_size=25, margin =(-11, 0, 0, 0), color=(0.2,1.0,0.6)) 30 | 31 | # Go to next line 32 | label.newline() 33 | label.newline() 34 | 35 | # Add some more parts 36 | label.add(text="This is the same label ..", color=(0.3,0.7,0.32)) 37 | 38 | # Go to next line 39 | label.newline() 40 | label.newline() 41 | 42 | # Add some more parts 43 | label.add(text="... but another line forced with ", color=(0.6,0.3,0.8)) 44 | label.add(text="newline() ", color=(1.0,0.6,0.2)) 45 | 46 | def make_random_color(): 47 | return (random.random(), random.random(), random.random()) 48 | 49 | def newline(): 50 | label.newline() 51 | label.add(text="New Line!", color=make_random_color()) 52 | 53 | f.set_actions({ 54 | "Add random text": lambda: label.add(text="Text ", color=make_random_color()), 55 | "Go to next line": newline 56 | }) 57 | 58 | run() 59 | -------------------------------------------------------------------------------- /Demos/B_Frame.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUIVerticalLayout import LUIVerticalLayout 5 | from LUIFrame import LUIFrame 6 | from LUILabel import LUILabel 7 | from LUIButton import LUIButton 8 | from LUIObject import LUIObject 9 | 10 | import random 11 | 12 | f = DemoFramework() 13 | f.prepare_demo("LUIFrame") 14 | 15 | # Constructor 16 | f.add_constructor_parameter("width", "200") 17 | f.add_constructor_parameter("height", "200") 18 | f.add_constructor_parameter("innerPadding", "5") 19 | f.add_constructor_parameter("scrollable", "False") 20 | f.add_constructor_parameter("style", "UIFrame.Raised") 21 | 22 | # Functions 23 | 24 | # Events 25 | f.construct_sourcecode("LUIFrame") 26 | 27 | # Construct a new frame 28 | frame = LUIFrame(parent=f.get_widget_node()) 29 | 30 | layout = LUIVerticalLayout(parent=frame, spacing=5) 31 | layout.add(LUILabel(text="This is some frame ..", color=(0.2, 0.6, 1.0, 1.0), font_size=20)) 32 | layout.add(LUILabel(text="It can contain arbitrary elements.")) 33 | layout.add(LUILabel(text="For example this button:")) 34 | layout.add(LUIButton(text="Fancy button")) 35 | 36 | # frame.fit_to_children() 37 | 38 | f.set_actions({ 39 | "Resize to 300x160": lambda: frame.set_size(300, 160), 40 | "Fit to children": lambda: frame.clear_size(), 41 | }) 42 | 43 | run() 44 | -------------------------------------------------------------------------------- /Demos/B_InputField.py: -------------------------------------------------------------------------------- 1 | 2 | from DemoFramework import DemoFramework 3 | from LUIInputField import LUIInputField 4 | 5 | import random 6 | 7 | f = DemoFramework() 8 | f.prepare_demo("LUIInputField") 9 | 10 | # Constructor 11 | f.add_constructor_parameter("value", "u''") 12 | f.add_constructor_parameter("placeholder", "u'Enter some text ..'") 13 | f.add_property("value", "string") 14 | f.add_event("changed") 15 | 16 | # Construct source code 17 | f.construct_sourcecode("LUIInputField") 18 | 19 | # Create 2 new buttons, and store them in a vertical layout 20 | field = LUIInputField(parent=f.get_widget_node()) 21 | 22 | f.set_actions({ 23 | "Set Random Text": lambda: field.set_value(u"Text: " + unicode(random.randint(100, 10000000))), 24 | "Clear": lambda: field.clear(), 25 | }) 26 | 27 | run() 28 | -------------------------------------------------------------------------------- /Demos/B_Label.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUILabel import LUILabel 5 | 6 | import random 7 | 8 | f = DemoFramework() 9 | f.prepare_demo("LUILabel") 10 | 11 | # Constructor 12 | 13 | f.add_constructor_parameter("text", "Label") 14 | f.add_constructor_parameter("shadow", "True") 15 | f.add_constructor_parameter("font_size", "14") 16 | f.add_constructor_parameter("font", "'label'") 17 | 18 | # Functions 19 | f.add_public_function("get_text", [], "string") 20 | f.add_public_function("set_text", [("text", "string")]) 21 | 22 | f.add_property("text", "string") 23 | f.add_property("text_handle", "LUIText") 24 | 25 | # Events 26 | f.construct_sourcecode("LUILabel") 27 | 28 | # Create a new label 29 | label = LUILabel(parent=f.get_widget_node(), text="This is a fancy label") 30 | 31 | f.set_actions({ 32 | "Set Random Text": lambda: label.set_text(str(random.randint(100, 10000))), 33 | "Set Random Color": lambda: label.set_color(random.random(), random.random(), random.random(), 1) 34 | }) 35 | 36 | run() 37 | -------------------------------------------------------------------------------- /Demos/B_Progressbar.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUIProgressbar import LUIProgressbar 5 | from LUISlider import LUISlider 6 | from LUILabel import LUILabel 7 | from LUIVerticalLayout import LUIVerticalLayout 8 | 9 | import random 10 | 11 | f = DemoFramework() 12 | f.prepare_demo("LUIProgressbar") 13 | 14 | # Constructor 15 | f.add_constructor_parameter("show_label", "False") 16 | 17 | # Functions 18 | f.add_public_function("get_value", [], "float") 19 | f.add_public_function("set_value", [("value", "float")]) 20 | 21 | f.add_property("value", "float") 22 | 23 | # Events 24 | f.construct_sourcecode("LUIProgressbar") 25 | 26 | # Create the checkbox 27 | layout = LUIVerticalLayout(parent=f.get_widget_node(), spacing=10) 28 | 29 | LUILabel(parent=layout.cell(), text="This is a progressbar:", color=(1, 1, 1, 0.4)) 30 | bar = LUIProgressbar(parent=layout.cell(), width=200.0) 31 | 32 | LUILabel(parent=layout.cell(), text="You can control it with this slider:", color=(1, 1, 1, 0.4)) 33 | slider = LUISlider(parent=layout.cell(), width=200.0, filled=True) 34 | slider.bind("changed", lambda event: bar.set_value(slider.value * 100.0)) 35 | 36 | f.set_actions({ 37 | "Set to 30%": lambda: bar.set_value(30), 38 | }) 39 | 40 | run() 41 | -------------------------------------------------------------------------------- /Demos/B_Radiobox.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUIRadiobox import LUIRadiobox 5 | from LUIRadioboxGroup import LUIRadioboxGroup 6 | from LUIVerticalLayout import LUIVerticalLayout 7 | 8 | import random 9 | 10 | f = DemoFramework() 11 | f.prepare_demo("LUIRadiobox") 12 | 13 | # Constructor 14 | f.add_constructor_parameter("group", "None") 15 | f.add_constructor_parameter("value", "None") 16 | f.add_constructor_parameter("label", "'Radiobox'") 17 | 18 | # Functions 19 | f.add_public_function("get_value", [], "object") 20 | f.add_public_function("get_label", [], "LUILabel") 21 | f.add_public_function("set_active", [], "void") 22 | 23 | f.add_property("value", "object") 24 | f.add_property("label", "LUILabel") 25 | 26 | # Events 27 | f.add_event("changed") 28 | f.construct_sourcecode("LUIRadiobox") 29 | 30 | # Create a group to connect the boxes 31 | group = LUIRadioboxGroup() 32 | 33 | # Create a layout for the boxes 34 | grid = LUIVerticalLayout(parent=f.get_widget_node(), spacing=5) 35 | 36 | # Create the boxes 37 | boxes = [] 38 | for i in range(1, 4): 39 | boxes.append(LUIRadiobox(group=group, value=i, label="Radiobox {0}".format(i), active=i==2)) 40 | grid.add(boxes[-1]) 41 | 42 | f.set_actions({ 43 | "Select Box 1": lambda: boxes[0].set_active(), 44 | "Select Box 2": lambda: boxes[1].set_active(), 45 | "Select Box 3": lambda: boxes[2].set_active(), 46 | "Set Random Text": lambda: boxes[0].label.set_text("Text: " + str(random.randint(100, 10000))), 47 | }) 48 | 49 | run() 50 | -------------------------------------------------------------------------------- /Demos/B_Slider.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from DemoFramework import DemoFramework 4 | from LUISlider import LUISlider 5 | from LUILabel import LUILabel 6 | from LUIVerticalLayout import LUIVerticalLayout 7 | 8 | import random 9 | 10 | f = DemoFramework() 11 | f.prepare_demo("LUISlider") 12 | 13 | # Constructor 14 | f.add_constructor_parameter("filled", "False") 15 | f.add_constructor_parameter("min_value", "0.0") 16 | f.add_constructor_parameter("max_value", "0.0") 17 | f.add_constructor_parameter("value", "None") 18 | 19 | # Functions 20 | f.add_public_function("get_value", [], "float") 21 | f.add_public_function("set_value", [("value", "float")]) 22 | 23 | f.add_property("value", "float") 24 | 25 | # Events 26 | f.add_event("changed") 27 | f.construct_sourcecode("LUISlider") 28 | 29 | # Create the checkbox 30 | layout = LUIVerticalLayout(parent=f.get_widget_node(), spacing=10) 31 | 32 | LUILabel(parent=layout.cell(), text="This is a filled slider:", color=(1, 1, 1, 0.4)) 33 | slider = LUISlider(parent=layout.cell(), width=200.0) 34 | 35 | LUILabel(parent=layout.cell(), text="This is a regular slider:", color=(1, 1, 1, 0.4)) 36 | slider_nofill = LUISlider(parent=layout.cell(), width=200.0, filled=False) 37 | 38 | f.set_actions({ 39 | "Set to 30%": lambda: slider.set_value(0.3), 40 | }) 41 | 42 | run() 43 | -------------------------------------------------------------------------------- /Demos/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | This directory contains various LUI demos. You should start with the demos 4 | 01 and 02. 5 | 6 | After that, you can try out the demos starting with B_, showing builtin 7 | LUI components. 8 | -------------------------------------------------------------------------------- /Demos/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Demos/__init__.py -------------------------------------------------------------------------------- /Demos/res/DemoBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Demos/res/DemoBackground.png -------------------------------------------------------------------------------- /Demos/res/LUILogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Demos/res/LUILogo.png -------------------------------------------------------------------------------- /Demos/res/LUILogoBlack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Demos/res/LUILogoBlack.png -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 tobspr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Misc/Draft.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Misc/Draft.psd -------------------------------------------------------------------------------- /Misc/Draft2.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Misc/Draft2.psd -------------------------------------------------------------------------------- /Misc/Draft3.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Misc/Draft3.psd -------------------------------------------------------------------------------- /Misc/LUIGenerateGrid.py: -------------------------------------------------------------------------------- 1 | 2 | from os import makedirs 3 | from os.path import dirname, join, isdir 4 | from panda3d.core import * 5 | 6 | 7 | # Configuration 8 | # source = raw_input("Source png file: ") 9 | # destPath = dirname(source) 10 | # borderSize = int(raw_input("Border size in pixel: ")) 11 | 12 | source = "btn_gray.png" 13 | destPath = "../Builtin/res/" 14 | destName = "ButtonDefault_#.png" 15 | borderSize = 3 16 | 17 | def extractSubImage(x, y, w, h, name): 18 | print "Extracting sub image to",name 19 | subPNM = PNMImage(w, h, 4) 20 | subPNM.copySubImage(img, 0, 0, x, y, w, h) 21 | suffix = destName.replace("#", name) 22 | subPNM.write(destPath + suffix) 23 | 24 | 25 | 26 | img = PNMImage(source) 27 | w, h = img.getReadXSize(), img.getReadYSize() 28 | 29 | if not isdir(destPath): 30 | makedirs(destPath) 31 | 32 | # top left 33 | extractSubImage(0, 0, borderSize, borderSize, "TL") 34 | 35 | # top right 36 | extractSubImage(w-borderSize, 0, borderSize, borderSize, "TR") 37 | 38 | # bottom left 39 | extractSubImage(0, h-borderSize, borderSize, borderSize, "BL") 40 | 41 | # bottom right 42 | extractSubImage(w-borderSize, h-borderSize, borderSize, borderSize, "BR") 43 | 44 | # top 45 | extractSubImage(borderSize, 0, w-2*borderSize, borderSize, "Top") 46 | 47 | # bottom 48 | extractSubImage(borderSize, h - borderSize, w-2*borderSize, borderSize, "Bottom") 49 | 50 | # left 51 | extractSubImage(0, borderSize, borderSize, h-2*borderSize, "Left") 52 | 53 | # right 54 | extractSubImage(w-borderSize, borderSize, borderSize, h-2*borderSize, "Right") 55 | 56 | # mid 57 | # extractSubImage(borderSize, borderSize, w-2*borderSize, h-2*borderSize, "Mid") 58 | extractSubImage(borderSize, borderSize, 1, h-2*borderSize, "Mid") 59 | -------------------------------------------------------------------------------- /Misc/Metro.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Misc/Metro.psd -------------------------------------------------------------------------------- /Misc/blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Misc/blank.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/tobspr/LUI.svg?branch=master)](https://travis-ci.org/tobspr/LUI) 2 | 3 | # Lightweight User Interface 4 | 5 | 6 | 7 | 8 | ### Requirements 9 | 10 | - **Panda3D SDK** (recent devel version) 11 | - **CMake** 12 | 13 | ### Installation 14 | 15 | Run `python update_module_builder.py`. This will create a build file in the current directory, which you can then run with `python build.py`. 16 | Now there should be a `lui.pyd` or `lui.so` depending on your system. 17 | 18 | If you are on **windows**, copy the .pyd into `PATH_TO_PANDA_SDK/panda3d/lui.pyd`. 19 | 20 | If you are on **linux**, copy the .so into `usr/lib/panda3d/lui.so` 21 | 22 | 23 | ### Running the Samples 24 | 25 | You can find various samples for the different LUI components in the `Demos` folder. 26 | 27 | ### Documentation 28 | 29 | There is no official documentation yet, however if you look at the `Demos` folder, there should be a lot of self-explanatory code. 30 | -------------------------------------------------------------------------------- /Skins/Default/GenerateAtlas.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd res 4 | ppython ../../../Misc/LUIAtlasGen.py 5 | pause 6 | -------------------------------------------------------------------------------- /Skins/Default/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/__init__.py -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-Black.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-BlackIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-BlackIt.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-Bold.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-BoldIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-BoldIt.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-ExtraLight.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-ExtraLightIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-ExtraLightIt.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-It.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-It.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-Light.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-LightIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-LightIt.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-Regular.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-Semibold.ttf -------------------------------------------------------------------------------- /Skins/Default/font/SourceSansPro-SemiboldIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/font/SourceSansPro-SemiboldIt.ttf -------------------------------------------------------------------------------- /Skins/Default/res/ButtonDefault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonDefault.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonDefaultFocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonDefaultFocus.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonDefaultFocus_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonDefaultFocus_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonDefaultFocus_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonDefaultFocus_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonDefault_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonDefault_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonDefault_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonDefault_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonGreen.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonGreenFocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonGreenFocus.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonGreenFocus_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonGreenFocus_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonGreenFocus_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonGreenFocus_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonGreen_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonGreen_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ButtonGreen_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ButtonGreen_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Checkbox_Checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Checkbox_Checked.png -------------------------------------------------------------------------------- /Skins/Default/res/Checkbox_CheckedHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Checkbox_CheckedHover.png -------------------------------------------------------------------------------- /Skins/Default/res/Checkbox_Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Checkbox_Default.png -------------------------------------------------------------------------------- /Skins/Default/res/Checkbox_DefaultHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Checkbox_DefaultHover.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerActiveColorOverlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerActiveColorOverlay.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerFieldHandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerFieldHandle.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerFieldOverlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerFieldOverlay.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerHueHandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerHueHandle.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerHueSlider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerHueSlider.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerPreviewBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerPreviewBg.png -------------------------------------------------------------------------------- /Skins/Default/res/ColorpickerPreviewOverlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ColorpickerPreviewOverlay.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_BL.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_BR.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_Bottom.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_Mid.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_TL.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_TR.png -------------------------------------------------------------------------------- /Skins/Default/res/Frame_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Frame_Top.png -------------------------------------------------------------------------------- /Skins/Default/res/HorizontalListDivider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/HorizontalListDivider.png -------------------------------------------------------------------------------- /Skins/Default/res/InputField.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/InputField.png -------------------------------------------------------------------------------- /Skins/Default/res/InputField_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/InputField_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/InputField_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/InputField_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Keymarker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Keymarker.png -------------------------------------------------------------------------------- /Skins/Default/res/Keymarker_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Keymarker_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/Keymarker_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Keymarker_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ListDivider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ListDivider.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_BL.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_BR.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_Bottom.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_Mid.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_TL.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_TR.png -------------------------------------------------------------------------------- /Skins/Default/res/Popup_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Popup_Top.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarBg.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarBg_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarBg_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarBg_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarBg_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarFg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarFg.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarFg_Finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarFg_Finish.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarFg_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarFg_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ProgressbarFg_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ProgressbarFg_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Radiobox_Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Radiobox_Active.png -------------------------------------------------------------------------------- /Skins/Default/res/Radiobox_ActiveHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Radiobox_ActiveHover.png -------------------------------------------------------------------------------- /Skins/Default/res/Radiobox_Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Radiobox_Default.png -------------------------------------------------------------------------------- /Skins/Default/res/Radiobox_DefaultHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Radiobox_DefaultHover.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollShadowBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollShadowBottom.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollShadowBottom_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollShadowBottom_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollShadowBottom_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollShadowBottom_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollShadowTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollShadowTop.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollShadowTop_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollShadowTop_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollShadowTop_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollShadowTop_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollbarHandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollbarHandle.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollbarHandle_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollbarHandle_Bottom.png -------------------------------------------------------------------------------- /Skins/Default/res/ScrollbarHandle_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/ScrollbarHandle_Top.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectbox.png -------------------------------------------------------------------------------- /Skins/Default/res/SelectboxActive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SelectboxActive.png -------------------------------------------------------------------------------- /Skins/Default/res/SelectboxActive_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SelectboxActive_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/SelectboxOpen_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SelectboxOpen_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectbox_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectbox_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectbox_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectbox_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/SelectdropDivider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SelectdropDivider.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_BL.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_BR.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_Bottom.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_Mid.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_TL.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_TR.png -------------------------------------------------------------------------------- /Skins/Default/res/Selectdrop_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/Selectdrop_Top.png -------------------------------------------------------------------------------- /Skins/Default/res/SliderBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SliderBg.png -------------------------------------------------------------------------------- /Skins/Default/res/SliderBgFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SliderBgFill.png -------------------------------------------------------------------------------- /Skins/Default/res/SliderBgFill_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SliderBgFill_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/SliderBg_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SliderBg_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/SliderBg_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SliderBg_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/SliderKnob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SliderKnob.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_BL.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_BR.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_Bottom.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_Left.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_Mid.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_Right.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_TL.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_TR.png -------------------------------------------------------------------------------- /Skins/Default/res/SunkenFrame_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/SunkenFrame_Top.png -------------------------------------------------------------------------------- /Skins/Default/res/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/atlas.png -------------------------------------------------------------------------------- /Skins/Default/res/blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Default/res/blank.png -------------------------------------------------------------------------------- /Skins/Metro/GenerateAtlas.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd res 4 | ppython ../../../Misc/LUIAtlasGen.py 5 | pause 6 | -------------------------------------------------------------------------------- /Skins/Metro/LUIMetroSkin.py: -------------------------------------------------------------------------------- 1 | 2 | from panda3d.lui import LUIFontPool, LUIAtlasPool 3 | from panda3d.core import Filename 4 | import os 5 | from os.path import join 6 | 7 | from LUISkin import LUISkin 8 | from LUILabel import LUILabel 9 | 10 | class LUIMetroSkin(LUISkin): 11 | 12 | """ Simple Metro / Flat UI skin """ 13 | 14 | skin_location = os.path.dirname(os.path.abspath(__file__)) 15 | 16 | def load(self): 17 | LUIFontPool.get_global_ptr().register_font( 18 | "default", loader.loadFont(self.get_resource("font/Roboto-Medium.ttf"))) 19 | 20 | label_font = loader.loadFont(self.get_resource("font/Roboto-Medium.ttf")) 21 | label_font.set_pixels_per_unit(32) 22 | LUIFontPool.get_global_ptr().register_font("label", label_font) 23 | 24 | headerFont = loader.loadFont(self.get_resource("font/Roboto-Light.ttf")) 25 | headerFont.set_pixels_per_unit(80) 26 | 27 | LUIFontPool.get_global_ptr().register_font("header", headerFont) 28 | 29 | LUIAtlasPool.get_global_ptr().load_atlas("skin", 30 | self.get_resource("res/atlas.txt"), 31 | self.get_resource("res/atlas.png")) 32 | 33 | # Label color 34 | # LUILabel.DEFAULT_COLOR = (0.0, 0.0, 0.0, 0.6) 35 | # LUILabel.DEFAULT_USE_SHADOW = False 36 | -------------------------------------------------------------------------------- /Skins/Metro/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/__init__.py -------------------------------------------------------------------------------- /Skins/Metro/border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/border.png -------------------------------------------------------------------------------- /Skins/Metro/copy_frames.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from shutil import copyfile as copy 4 | os.chdir("res/") 5 | 6 | for f in os.listdir("."): 7 | if f.startswith("Popup_") or f.startswith("Frame_") or f.startswith("SunkenFrame_"): 8 | copy("../flat.png" if "_Mid" in f else "../border.png", f) 9 | 10 | 11 | copy("ButtonDefault.png", "ButtonDefaultFocus.png") 12 | copy("ButtonDefault.png", "ButtonDefaultFocus_Left.png") 13 | copy("ButtonDefault.png", "ButtonDefaultFocus_Right.png") 14 | copy("ButtonDefault.png", "ButtonDefault_Left.png") 15 | copy("ButtonDefault.png", "ButtonDefault_Right.png") 16 | 17 | copy("ButtonGreen.png", "ButtonGreenFocus.png") 18 | copy("ButtonGreen.png", "ButtonGreenFocus_Left.png") 19 | copy("ButtonGreen.png", "ButtonGreenFocus_Right.png") 20 | copy("ButtonGreen.png", "ButtonGreen_Left.png") 21 | copy("ButtonGreen.png", "ButtonGreen_Right.png") 22 | 23 | copy("Selectbox.png", "Selectbox_Left.png") 24 | copy("Selectbox.png", "SelectboxActive.png") 25 | copy("Selectbox.png", "SelectboxActive_Left.png") 26 | 27 | copy("ProgressbarFg.png", "ProgressbarFg_Right.png") 28 | copy("ProgressbarFg.png", "ProgressbarFg_Left.png") 29 | copy("ProgressbarFg.png", "ProgressbarFg_Finish.png") 30 | copy("ProgressbarBg.png", "ProgressbarBg_Right.png") 31 | copy("ProgressbarBg.png", "ProgressbarBg_Left.png") 32 | 33 | copy("SliderBgFill.png", "SliderBgFill_Left.png") 34 | copy("SliderBg.png", "SliderBg_Left.png") 35 | copy("SliderBg.png", "SliderBg_Right.png") 36 | 37 | copy("InputField.png", "InputField_Left.png") 38 | copy("InputField.png", "InputField_Right.png") 39 | 40 | for align in "TR TL BR BL Top Right Bottom Left".split(): 41 | copy("Selectdrop_Mid.png", "Selectdrop_" + align + ".png") 42 | -------------------------------------------------------------------------------- /Skins/Metro/flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/flat.png -------------------------------------------------------------------------------- /Skins/Metro/font/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/font/Roboto-Bold.ttf -------------------------------------------------------------------------------- /Skins/Metro/font/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/font/Roboto-Light.ttf -------------------------------------------------------------------------------- /Skins/Metro/font/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/font/Roboto-Medium.ttf -------------------------------------------------------------------------------- /Skins/Metro/font/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/font/Roboto-Thin.ttf -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonDefault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonDefault.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonDefaultFocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonDefaultFocus.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonDefaultFocus_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonDefaultFocus_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonDefaultFocus_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonDefaultFocus_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonDefault_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonDefault_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonDefault_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonDefault_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonGreen.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonGreenFocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonGreenFocus.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonGreenFocus_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonGreenFocus_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonGreenFocus_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonGreenFocus_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonGreen_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonGreen_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ButtonGreen_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ButtonGreen_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Checkbox_Checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Checkbox_Checked.png -------------------------------------------------------------------------------- /Skins/Metro/res/Checkbox_CheckedHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Checkbox_CheckedHover.png -------------------------------------------------------------------------------- /Skins/Metro/res/Checkbox_Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Checkbox_Default.png -------------------------------------------------------------------------------- /Skins/Metro/res/Checkbox_DefaultHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Checkbox_DefaultHover.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerActiveColorOverlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerActiveColorOverlay.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerFieldHandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerFieldHandle.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerFieldOverlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerFieldOverlay.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerHueHandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerHueHandle.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerHueSlider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerHueSlider.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerPreviewBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerPreviewBg.png -------------------------------------------------------------------------------- /Skins/Metro/res/ColorpickerPreviewOverlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ColorpickerPreviewOverlay.png -------------------------------------------------------------------------------- /Skins/Metro/res/Draft3.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Draft3.psd -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_BL.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_BR.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_Bottom.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_Mid.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_TL.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_TR.png -------------------------------------------------------------------------------- /Skins/Metro/res/Frame_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Frame_Top.png -------------------------------------------------------------------------------- /Skins/Metro/res/HorizontalListDivider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/HorizontalListDivider.png -------------------------------------------------------------------------------- /Skins/Metro/res/InputField.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/InputField.png -------------------------------------------------------------------------------- /Skins/Metro/res/InputField_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/InputField_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/InputField_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/InputField_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Keymarker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Keymarker.png -------------------------------------------------------------------------------- /Skins/Metro/res/Keymarker_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Keymarker_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/Keymarker_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Keymarker_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ListDivider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ListDivider.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_BL.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_BR.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_Bottom.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_Mid.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_TL.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_TR.png -------------------------------------------------------------------------------- /Skins/Metro/res/Popup_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Popup_Top.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarBg.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarBg_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarBg_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarBg_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarBg_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarFg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarFg.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarFg_Finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarFg_Finish.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarFg_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarFg_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ProgressbarFg_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ProgressbarFg_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Radiobox_Active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Radiobox_Active.png -------------------------------------------------------------------------------- /Skins/Metro/res/Radiobox_ActiveHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Radiobox_ActiveHover.png -------------------------------------------------------------------------------- /Skins/Metro/res/Radiobox_Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Radiobox_Default.png -------------------------------------------------------------------------------- /Skins/Metro/res/Radiobox_DefaultHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Radiobox_DefaultHover.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollShadowBottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollShadowBottom.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollShadowBottom_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollShadowBottom_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollShadowBottom_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollShadowBottom_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollShadowTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollShadowTop.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollShadowTop_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollShadowTop_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollShadowTop_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollShadowTop_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollbarHandle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollbarHandle.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollbarHandle_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollbarHandle_Bottom.png -------------------------------------------------------------------------------- /Skins/Metro/res/ScrollbarHandle_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/ScrollbarHandle_Top.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectbox.png -------------------------------------------------------------------------------- /Skins/Metro/res/SelectboxActive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SelectboxActive.png -------------------------------------------------------------------------------- /Skins/Metro/res/SelectboxActive_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SelectboxActive_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/SelectboxOpen_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SelectboxOpen_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectbox_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectbox_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectbox_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectbox_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/SelectdropDivider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SelectdropDivider.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_BL.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_BR.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_Bottom.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_Mid.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_TL.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_TR.png -------------------------------------------------------------------------------- /Skins/Metro/res/Selectdrop_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/Selectdrop_Top.png -------------------------------------------------------------------------------- /Skins/Metro/res/SliderBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SliderBg.png -------------------------------------------------------------------------------- /Skins/Metro/res/SliderBgFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SliderBgFill.png -------------------------------------------------------------------------------- /Skins/Metro/res/SliderBgFill_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SliderBgFill_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/SliderBg_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SliderBg_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/SliderBg_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SliderBg_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/SliderKnob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SliderKnob.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_BL.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_BR.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_Bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_Bottom.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_Left.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_Mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_Mid.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_Right.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_TL.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_TR.png -------------------------------------------------------------------------------- /Skins/Metro/res/SunkenFrame_Top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/SunkenFrame_Top.png -------------------------------------------------------------------------------- /Skins/Metro/res/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/atlas.png -------------------------------------------------------------------------------- /Skins/Metro/res/atlas.txt: -------------------------------------------------------------------------------- 1 | ColorpickerFieldOverlay 0 0 132 132 2 | ColorpickerHueSlider 132 0 24 132 3 | ColorpickerActiveColorOverlay 156 0 44 44 4 | SelectboxOpen_Right 200 0 37 36 5 | Selectbox_Right 200 36 37 36 6 | ColorpickerHueHandle 156 72 50 22 7 | ColorpickerPreviewBg 206 72 31 31 8 | ColorpickerPreviewOverlay 156 44 27 27 9 | ScrollShadowBottom_Left 237 0 18 18 10 | ScrollShadowBottom_Right 237 18 18 18 11 | ScrollShadowTop_Left 237 36 18 18 12 | ScrollShadowTop_Right 237 54 18 18 13 | Checkbox_Checked 183 44 17 17 14 | Checkbox_CheckedHover 237 72 17 17 15 | Checkbox_Default 237 89 17 17 16 | Checkbox_DefaultHover 156 94 17 17 17 | Radiobox_Active 173 94 17 17 18 | Radiobox_ActiveHover 190 103 17 17 19 | Radiobox_Default 207 103 17 17 20 | Radiobox_DefaultHover 224 106 17 17 21 | ColorpickerFieldHandle 156 111 16 17 22 | Keymarker_Left 241 106 6 27 23 | Keymarker_Right 247 106 6 27 24 | SliderKnob 172 111 8 18 25 | ScrollbarHandle_Top 183 61 11 6 26 | ScrollbarHandle_Bottom 183 67 11 5 27 | InputField 255 0 1 39 28 | InputField_Left 255 39 1 39 29 | InputField_Right 254 72 1 39 30 | ButtonDefault 255 78 1 36 31 | ButtonDefaultFocus 253 106 1 36 32 | ButtonDefaultFocus_Left 180 111 1 36 33 | ButtonDefaultFocus_Right 181 111 1 36 34 | ButtonDefault_Left 182 111 1 36 35 | ButtonDefault_Right 183 111 1 36 36 | ButtonGreen 184 111 1 36 37 | ButtonGreenFocus 185 111 1 36 38 | ButtonGreenFocus_Left 186 111 1 36 39 | ButtonGreenFocus_Right 187 111 1 36 40 | ButtonGreen_Left 188 111 1 36 41 | ButtonGreen_Right 189 111 1 36 42 | Selectbox 254 111 1 36 43 | SelectboxActive 255 114 1 36 44 | SelectboxActive_Left 190 120 1 36 45 | Selectbox_Left 191 120 1 36 46 | Keymarker 192 120 1 27 47 | ScrollShadowBottom 193 120 1 18 48 | ScrollShadowTop 194 120 1 18 49 | ScrollbarHandle 156 71 11 1 50 | ProgressbarBg 194 61 1 5 51 | ProgressbarBg_Left 195 61 1 5 52 | ProgressbarBg_Right 196 61 1 5 53 | ProgressbarFg 197 61 1 5 54 | ProgressbarFg_Finish 198 61 1 5 55 | ProgressbarFg_Left 199 61 1 5 56 | ProgressbarFg_Right 194 66 1 5 57 | SliderBg 195 66 1 5 58 | SliderBgFill 196 66 1 5 59 | SliderBgFill_Left 197 66 1 5 60 | SliderBg_Left 198 66 1 5 61 | SliderBg_Right 199 66 1 5 62 | blank 167 71 1 1 63 | Frame_BL 168 71 1 1 64 | Frame_Bottom 169 71 1 1 65 | Frame_BR 170 71 1 1 66 | Frame_Left 171 71 1 1 67 | Frame_Mid 172 71 1 1 68 | Frame_Right 173 71 1 1 69 | Frame_TL 174 71 1 1 70 | Frame_Top 175 71 1 1 71 | Frame_TR 176 71 1 1 72 | HorizontalListDivider 177 71 1 1 73 | ListDivider 178 71 1 1 74 | Popup_BL 179 71 1 1 75 | Popup_Bottom 180 71 1 1 76 | Popup_BR 181 71 1 1 77 | Popup_Left 182 71 1 1 78 | Popup_Mid 194 71 1 1 79 | Popup_Right 195 71 1 1 80 | Popup_TL 196 71 1 1 81 | Popup_Top 197 71 1 1 82 | Popup_TR 198 71 1 1 83 | SelectdropDivider 199 71 1 1 84 | Selectdrop_BL 190 94 1 1 85 | Selectdrop_Bottom 191 94 1 1 86 | Selectdrop_BR 192 94 1 1 87 | Selectdrop_Left 193 94 1 1 88 | Selectdrop_Mid 194 94 1 1 89 | Selectdrop_Right 195 94 1 1 90 | Selectdrop_TL 196 94 1 1 91 | Selectdrop_Top 197 94 1 1 92 | Selectdrop_TR 198 94 1 1 93 | SunkenFrame_BL 199 94 1 1 94 | SunkenFrame_Bottom 200 94 1 1 95 | SunkenFrame_BR 201 94 1 1 96 | SunkenFrame_Left 202 94 1 1 97 | SunkenFrame_Mid 203 94 1 1 98 | SunkenFrame_Right 204 94 1 1 99 | SunkenFrame_TL 205 94 1 1 100 | SunkenFrame_Top 190 95 1 1 101 | SunkenFrame_TR 191 95 1 1 102 | -------------------------------------------------------------------------------- /Skins/Metro/res/blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/Metro/res/blank.png -------------------------------------------------------------------------------- /Skins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobspr/LUI/35035090590c5cde8b725edea8eb9bf6c6c2ad33/Skins/__init__.py -------------------------------------------------------------------------------- /Tests/Test.py: -------------------------------------------------------------------------------- 1 | 2 | import sys 3 | sys.path.insert(0, "../Builtin") 4 | 5 | from direct.showbase.ShowBase import ShowBase 6 | from direct.showbase.DirectObject import DirectObject 7 | 8 | from panda3d.core import * 9 | load_prc_file_data("", """ 10 | text-minfilter linear 11 | text-magfilter linear 12 | text-pixels-per-unit 32 13 | sync-video #f 14 | textures-power-2 none 15 | notify-level-lui info 16 | show-frame-rate-meter #t 17 | win-size 780 630 18 | window-title LUI Demo 19 | win-fixed-size #f 20 | """) 21 | 22 | from LUIRegion import LUIRegion 23 | from LUIObject import LUIObject 24 | from LUIInputHandler import LUIInputHandler 25 | from LUISprite import LUISprite 26 | from LUIVerticalLayout import LUIVerticalLayout 27 | from LUISkin import LUIDefaultSkin 28 | from LUIFrame import LUIFrame 29 | from LUIFormattedLabel import LUIFormattedLabel 30 | from LUIInputField import LUIInputField 31 | from LUIButton import LUIButton 32 | from LUILabel import LUILabel 33 | from LUICheckbox import LUICheckbox 34 | from LUIRadiobox import LUIRadiobox 35 | from LUIRadioboxGroup import LUIRadioboxGroup 36 | 37 | s = ShowBase() 38 | base.win.set_clear_color(Vec4(0.05, 0.05, 0.05, 1.0)) 39 | 40 | skin = LUIDefaultSkin() 41 | skin.load() 42 | 43 | region = LUIRegion.make("LUI", base.win) 44 | handler = LUIInputHandler() 45 | base.mouseWatcher.attach_new_node(handler) 46 | region.set_input_handler(handler) 47 | 48 | # bg = LUISprite(region.root, "blank", "skin") 49 | # bg.pos = 200, 200 50 | # bg.size = 200, 300 51 | 52 | container = LUIFrame( 53 | parent = region.root, pos = (200, 200), height=300, 54 | style = LUIFrame.FS_sunken) 55 | 56 | 57 | # label_tl = LUILabel(parent=container, text="Top Left", top_left=(0,0)) 58 | # label_tr = LUILabel(parent=container, text="Top Right", top_right=(0,0)) 59 | # label_bl = LUILabel(parent=container, text="Bottom Left", bottom_left=(0,0)) 60 | # label_br = LUILabel(parent=container, text="Bottom Right", bottom_right=(0,0)) 61 | 62 | # button = LUIButton(parent=container, top_left=(0, 0), text="Well this one .. is a long button! (A really long one!) ............ really long!") 63 | # button.bind("click", lambda event: button.set_text("Hello!")) 64 | container.size = 300, 300 65 | # group = LUIRadioboxGroup() 66 | # box = LUIRadiobox(parent=container, group=group, top=50) 67 | # box2 = LUICheckbox(parent=container, top=100) 68 | 69 | layout = LUIVerticalLayout(parent=container) 70 | # layout.height = 280 71 | # layout.width = 300 72 | 73 | LUILabel(parent=layout.cell(), text="Hello") 74 | LUILabel(parent=layout.cell(), text="World") 75 | LUILabel(parent=layout.cell(100), text="100px row") 76 | LUILabel(parent=layout.cell(), text="Next") 77 | LUIButton(parent=layout.cell(), text="SomeButton") 78 | LUILabel(parent=layout.cell('*'), text="Fill column") 79 | LUILabel(parent=layout.cell(), text="Last column") 80 | 81 | for i in range(5): 82 | base.graphicsEngine.render_frame() 83 | 84 | region.root.ls() 85 | 86 | s.run() 87 | -------------------------------------------------------------------------------- /Tests/Test_Performance.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from common import * 4 | 5 | 6 | @timeit(200, 100) 7 | def test_01_create_lui_objects(): 8 | for i in range(100): 9 | object = LUIObject(parent=region.root) 10 | region.root.remove_all_children() 11 | 12 | @timeit(200, 100) 13 | def test_02_create_lui_sprites(): 14 | for i in range(100): 15 | object = LUISprite(region.root, "blank", "skin") 16 | region.root.remove_all_children() 17 | 18 | @timeit(200, 2500) 19 | def test_03_reattach_lui_objects(): 20 | object = LUIObject() 21 | object2 = LUIObject(parent=region.root) 22 | for i in range(2500): 23 | object.parent = region.root 24 | object.parent = None 25 | object.parent = object2 26 | object.parent = None 27 | region.root.remove_all_children() 28 | 29 | @timeit(200, 2500) 30 | def test_04_positioning(): 31 | object = LUIObject(parent=region.root) 32 | for i in range(2500): 33 | object.left = 3 34 | object.right = 8 35 | object.top = 3 36 | object.bottom = -2 37 | object.center_vertical = True 38 | object.center_horizontal = True 39 | object.centered = False, False 40 | object.top += 3 41 | region.root.remove_all_children() 42 | 43 | @timeit(40, 10) 44 | def test_05_vertical_layouts(): 45 | layout = LUIVerticalLayout(parent=region.root) 46 | for i in range(10): 47 | for k in range(10): 48 | obj = LUIObject() 49 | sprite = LUISprite(obj, "blank", "skin") 50 | layout.add(obj) 51 | layout.reset() 52 | region.root.remove_all_children() 53 | 54 | # Execute all tests 55 | [v() for k, v in sorted(dict(locals()).items()) if k.startswith("test_")] 56 | -------------------------------------------------------------------------------- /Tests/Unittests.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import print_function 3 | from common import * 4 | 5 | import unittest 6 | 7 | 8 | class Test_FluidBox(unittest.TestCase): 9 | 10 | def test_box(self): 11 | container = LUIObject(parent=region.root) 12 | sprite = LUISprite(container, "blank", "skin") 13 | sprite.size = 100, 100 14 | 15 | render_frames() 16 | self.assertEqual(sprite.size, (100, 100)) 17 | self.assertEqual(container.size, (100, 100)) 18 | region.root.remove_all_children() 19 | 20 | def test_region(self): 21 | render_frames() 22 | self.assertEqual(region.root.size, (512, 512)) 23 | 24 | if __name__ == "__main__": 25 | unittest.main() 26 | 27 | base.run() 28 | 29 | -------------------------------------------------------------------------------- /Tests/common.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import print_function 3 | 4 | import sys 5 | sys.path.insert(0, "../Builtin") 6 | 7 | from direct.showbase.ShowBase import ShowBase 8 | from direct.showbase.DirectObject import DirectObject 9 | 10 | from panda3d.core import * 11 | load_prc_file_data("", """ 12 | text-minfilter linear 13 | text-magfilter linear 14 | text-pixels-per-unit 32 15 | sync-video #f 16 | textures-power-2 none 17 | notify-level-lui warning 18 | show-frame-rate-meter #f 19 | win-size 512 512 20 | window-title LUI Performance Test 21 | win-fixed-size #f 22 | """) 23 | 24 | import time 25 | from functools import wraps 26 | from LUIRegion import LUIRegion 27 | from LUIObject import LUIObject 28 | from LUIInputHandler import LUIInputHandler 29 | from LUISprite import LUISprite 30 | from LUISkin import LUIDefaultSkin 31 | from panda3d.lui import LUIVerticalLayout 32 | from LUIFrame import LUIFrame 33 | from LUIFormattedLabel import LUIFormattedLabel 34 | from LUIInputField import LUIInputField 35 | 36 | base = ShowBase() 37 | base.win.set_clear_color(Vec4(0.0, 0.0, 0.0, 1.0)) 38 | skin = LUIDefaultSkin() 39 | skin.load() 40 | region = LUIRegion.make("LUI", base.win) 41 | handler = LUIInputHandler() 42 | base.mouseWatcher.attach_new_node(handler) 43 | region.set_input_handler(handler) 44 | 45 | class timeit(object): 46 | def __init__(self, num_iterations=100, internal_iterations=100): 47 | self._iterations = num_iterations 48 | self._internal_iterations = internal_iterations 49 | 50 | def __call__(self, func): 51 | def _wrap(*args, **kwargs): 52 | print("Timing", func.__name__, "..") 53 | start = time.time() 54 | for i in xrange(self._iterations): 55 | func(*args, **kwargs) 56 | duration = time.time() - start 57 | print(" + Total time: ", round(duration * 1000.0, 2), "ms, which is", 58 | round(duration / self._iterations * 1000.0, 2), "ms per iteration") 59 | print(" + This is", round(duration / (self._iterations * self._internal_iterations) * 1000.0, 5), 60 | "ms per internal iteration") 61 | return _wrap 62 | 63 | def render_frames(): 64 | for i in range(3): 65 | base.graphicsEngine.renderFrame() 66 | -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | generate_pdb=1 2 | module_name=lui 3 | require_lib_freetype=1 4 | -------------------------------------------------------------------------------- /source/config_lui.cxx: -------------------------------------------------------------------------------- 1 | // Filename: config_lui.cxx 2 | // Created by: tobspr (28Aug14) 3 | // 4 | //////////////////////////////////////////////////////////////////// 5 | 6 | #include "config_lui.h" 7 | 8 | #include "pandaSystem.h" 9 | #include "dconfig.h" 10 | 11 | #include "luiRegion.h" 12 | #include "luiInputHandler.h" 13 | #include "luiSprite.h" 14 | #include "luiBaseElement.h" 15 | #include "luiObject.h" 16 | #include "luiText.h" 17 | #include "luiEventData.h" 18 | #include "luiBaseLayout.h" 19 | #include "luiVerticalLayout.h" 20 | #include "luiHorizontalLayout.h" 21 | 22 | Configure(config_lui); 23 | NotifyCategoryDef(lui, ""); 24 | 25 | ConfigureFn(config_lui) { 26 | init_lui(); 27 | } 28 | 29 | void init_lui() { 30 | static bool initialized = false; 31 | if (initialized) { 32 | return; 33 | } 34 | initialized = true; 35 | 36 | LUIRegion::init_type(); 37 | LUIInputHandler::init_type(); 38 | LUIBaseElement::init_type(); 39 | LUISprite::init_type(); 40 | LUIObject::init_type(); 41 | LUIText::init_type(); 42 | LUIEventData::init_type(); 43 | LUIBaseLayout::init_type(); 44 | LUIVerticalLayout::init_type(); 45 | LUIHorizontalLayout::init_type(); 46 | } 47 | -------------------------------------------------------------------------------- /source/config_lui.h: -------------------------------------------------------------------------------- 1 | // Filename: config_lui.h 2 | // Created by: tobspr (28Aug14) 3 | // 4 | 5 | #ifndef CONFIG_LUI_H 6 | #define CONFIG_LUI_H 7 | 8 | #include "pandabase.h" 9 | #include "notifyCategoryProxy.h" 10 | #include "dconfig.h" 11 | 12 | #define EXPCL_LUI EXPORT_CLASS 13 | #define EXPTP_LUI EXPORT_TEMPL 14 | 15 | ConfigureDecl(config_lui, EXPCL_LUI, EXPTP_LUI); 16 | NotifyCategoryDecl(lui, EXPCL_LUI, EXPTP_LUI); 17 | 18 | extern EXPCL_LUI void init_lui(); 19 | 20 | using namespace std; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /source/luiAtlas.I: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @brief Checks whether an entry exists in the atlas. 4 | * @details This methods checks if an entry with the given name exists in the 5 | * atlas. If an entry was found, true is returned, otherwise false. 6 | * 7 | * @param name Entry name, case sensitive 8 | * @return true if the entry was found, false otherwise 9 | */ 10 | INLINE bool LUIAtlas::has_entry(const string& name) const { 11 | return _entries.count(name) != 0; 12 | } 13 | 14 | /** 15 | * @brief Returns an atlas entry. 16 | * @details This search for an atlas entry with the given name, and returns it. 17 | * If an entry was not found in the atlas, an assertion is raised. 18 | * This behaviour can be prevented by using LUIAtlas::has_entry() before. 19 | * 20 | * @param name Entry name, case sensitive 21 | * @return Handle to the atlas entry 22 | */ 23 | INLINE const LUIAtlasEntry& LUIAtlas::get_entry(const string& name) const { 24 | auto it = _entries.find(name); 25 | 26 | if (it == _entries.end()) { 27 | lui_cat.error() << "Entry '" << name << "' is not present in atlas" << endl; 28 | nassertr(false, _entries.begin()->second); 29 | } 30 | 31 | return it->second; 32 | } 33 | 34 | /** 35 | * @brief Returns the atlas texture 36 | * @details This returns a handle to the atlas texture, which can be used for 37 | * rendering. 38 | * @return Handle to the atlas texture 39 | */ 40 | INLINE Texture* LUIAtlas::get_texture() const { 41 | return _tex; 42 | } 43 | 44 | /** 45 | * @brief Returns the atlas size. 46 | * @details Returns the atlas size in pixels, this is a convenience function for 47 | * Texture::get_x_size(). It assumes the atlas has the same width and height. 48 | * @return Size of the atlas in pixels 49 | */ 50 | INLINE int LUIAtlas::get_size() const { 51 | return _tex->get_x_size(); 52 | } 53 | -------------------------------------------------------------------------------- /source/luiAtlas.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiAtlas.h" 3 | 4 | #include "samplerState.h" 5 | #include "virtualFileSystem.h" 6 | #include 7 | 8 | 9 | /** 10 | * @brief Loads a descriptor file 11 | * @details This loads a descriptor file previously created with LUIAtlasGen. 12 | * When the file was loaded, true is returned, otherwise an error is printed 13 | * and false is returned. 14 | * 15 | * @param descriptor_path Path to the generated atlas file, most times 'atlas.txt' 16 | * @return true if the atlas file was loaded, false otherwise 17 | */ 18 | bool LUIAtlas::load_descriptor_file(const string& descriptor_path) { 19 | 20 | lui_cat.info() << "Loading atlas description from " << descriptor_path << endl; 21 | 22 | // Get file handle 23 | VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 24 | PT(VirtualFile) file = vfs->get_file(descriptor_path); 25 | 26 | if (file == nullptr) { 27 | lui_cat.error() << "Could not find " << descriptor_path << endl; 28 | return false; 29 | } 30 | 31 | if (!file->is_regular_file()) { 32 | lui_cat.error() << "File '"<< descriptor_path << "' is not a regular file" << endl; 33 | return false; 34 | } 35 | 36 | string content = file->read_file(true); 37 | stringstream stream(content); 38 | 39 | string name; 40 | int x, y, w, h; 41 | while (stream >> name >> x >> y >> w >> h) 42 | { 43 | if (has_entry(name)) 44 | lui_cat.warning() << "Entry '" << name << "' is already contained in atlas, overriding .." << endl; 45 | _entries[name] = LUIAtlasEntry(x, y, w, h); 46 | } 47 | 48 | return true; 49 | } 50 | 51 | /** 52 | * @brief Loads an atlas texture 53 | * @details This loads the atlas texture, and prepares it for rendering by setting 54 | * several filtering properties on the texture. If the texture was not found, 55 | * returns false, otherwise returns true. Also returns false if the texture 56 | * has different dimensions in width / height. 57 | * 58 | * @param texture_path Path to the atlas texture 59 | * @return true if the texture was loaded successfully, false otherwise 60 | */ 61 | bool LUIAtlas::load_texture(const string& texture_path) { 62 | lui_cat.info() << "Loading atlas texture from " << texture_path << endl; 63 | 64 | _tex = TexturePool::load_texture(texture_path); 65 | 66 | // File not found 67 | if (_tex == nullptr) { 68 | lui_cat.error() << "Failed to load atlas texture from " << texture_path << endl; 69 | _tex = nullptr; 70 | return false; 71 | } 72 | 73 | // Non square 74 | if (_tex->get_x_size() != _tex->get_y_size()) { 75 | lui_cat.error() << "Cannot load non-square atlas texture!" << endl; 76 | _tex = nullptr; 77 | return false; 78 | } 79 | 80 | // Prepare the texture 81 | _tex->set_minfilter(SamplerState::FT_nearest); 82 | _tex->set_magfilter(SamplerState::FT_nearest); 83 | _tex->set_anisotropic_degree(0); 84 | return true; 85 | } 86 | -------------------------------------------------------------------------------- /source/luiAtlas.h: -------------------------------------------------------------------------------- 1 | // Filename: luiAtlas.h 2 | // Created by: tobspr (29Aug14) 3 | // 4 | 5 | #ifndef LUI_ATLAS_H 6 | #define LUI_ATLAS_H 7 | 8 | #include 9 | 10 | #include "pandabase.h" 11 | #include "pandasymbols.h" 12 | #include "luse.h" 13 | #include "texture.h" 14 | #include "texturePool.h" 15 | 16 | #include "config_lui.h" 17 | 18 | /** 19 | * @brief Stores an entry in the atlas 20 | * @details This is a container class for storing positions in the atlas. 21 | * It contains a start uv-coordinate and uv-size. 22 | * 23 | */ 24 | struct LUIAtlasEntry { 25 | LTexCoord pos; 26 | LTexCoord size; 27 | LUIAtlasEntry() : pos(0), size(0) {}; 28 | LUIAtlasEntry(float x, float y, float w, float h) : pos(x, y), size(w, h) {}; 29 | }; 30 | 31 | /** 32 | * @brief This is the container class for an atlas 33 | * @details This class manages the storage of a single atlas texture, including 34 | * storing a reference to the atlas texture, the atlas size, and the atlas entries. 35 | * It provides functions to load atlas descriptions generated by LUIAtlasGen too. 36 | */ 37 | class EXPCL_LUI LUIAtlas : public ReferenceCount { 38 | 39 | PUBLISHED: 40 | 41 | bool load_descriptor_file(const string& descriptor_path); 42 | bool load_texture(const string& texture_path); 43 | 44 | INLINE Texture* get_texture() const; 45 | 46 | INLINE bool has_entry(const string& name) const; 47 | INLINE const LUIAtlasEntry& get_entry(const string& name) const; 48 | 49 | INLINE int get_size() const; 50 | 51 | private: 52 | 53 | PT(Texture) _tex; 54 | pmap _entries; 55 | 56 | }; 57 | 58 | #include "luiAtlas.I" 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /source/luiAtlasDescriptor.I: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @brief Returns the stored texture 4 | * @details This returns the texture previously stored with 5 | * LUIAtlasDescriptor::set_texture(). Usually this is a handle to the atlas 6 | * texture. 7 | * @return Texture handle, or nullptr if no texture was set 8 | */ 9 | INLINE Texture* LUIAtlasDescriptor::get_texture() const { 10 | return _tex; 11 | } 12 | 13 | /** 14 | * @brief Returns the size of the sprite 15 | * @details This returns the size of the referenced sprite in pixels, previously 16 | * set with LUIAtlasDescriptor::set_size(). 17 | * 18 | * @return Texture size 19 | */ 20 | INLINE const LVector2& LUIAtlasDescriptor::get_size() const { 21 | return _size; 22 | } 23 | 24 | /** 25 | * @brief Returns the uv-start coordinate 26 | * @details Returns the start of the sprite in atlas space. This is the value 27 | * previously set with LUIAtlasDescriptor::set_uv_range(). 28 | * 29 | * @return uv-start coordinate 30 | */ 31 | INLINE const LTexCoord& LUIAtlasDescriptor::get_uv_begin() const { 32 | return _uv_begin; 33 | } 34 | 35 | /** 36 | * @brief Returns the uv-end coordinate 37 | * @details Returns the end of the sprite in atlas space. This is the value 38 | * previously set with LUIAtlasDescriptor::set_uv_range(). 39 | * 40 | * @return uv-end coordinate 41 | */ 42 | INLINE const LTexCoord& LUIAtlasDescriptor::get_uv_end() const { 43 | return _uv_end; 44 | } 45 | 46 | /** 47 | * @brief Sets the atlas texture 48 | * @details This sets the handle to the texture. This should only happen while 49 | * the descriptor gets created, and only the LUIAtlasPool has access to this 50 | * method. 51 | * 52 | * The descriptor will not keep track of the texture, so it is important 53 | * to ensure the texture handle stays valid while the descriptor exists. 54 | * 55 | * @param tex Handle to the atlas texture. 56 | */ 57 | INLINE void LUIAtlasDescriptor::set_texture(Texture* tex) { 58 | _tex = tex; 59 | } 60 | 61 | /** 62 | * @brief Sets the size of the contained sprite 63 | * @details This sets the size of the sprite in pixels. This can be useful at 64 | * some places, however it can also be deduced from the uv coordinates 65 | * and atlas size. 66 | * 67 | * @param size Size of the sprite in pixels 68 | */ 69 | INLINE void LUIAtlasDescriptor::set_size(const LVector2& size) { 70 | _size = size; 71 | } 72 | 73 | /** 74 | * @brief Sets the uv coordinates 75 | * @details This sets the uv coordinates of the sprite in atlas space, thus from 76 | * (0, 0) to (1, 1). uv_begin should be the upper-left coordinate of the sprite, 77 | * and uv_end should be the lower-right one. 78 | * 79 | * @param uv_begin Upper left coordinate in uv space 80 | * @param uv_end Lower right coordinate in uv space 81 | */ 82 | INLINE void LUIAtlasDescriptor::set_uv_range(const LTexCoord& uv_begin, const LTexCoord& uv_end) { 83 | _uv_begin = uv_begin; 84 | _uv_end = uv_end; 85 | } 86 | -------------------------------------------------------------------------------- /source/luiAtlasDescriptor.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiAtlasDescriptor.h" 3 | 4 | /** 5 | * @brief Constructs a new descriptor 6 | * @details This constructs a new atlas descriptor, with all values set to zero. 7 | * 8 | */ 9 | LUIAtlasDescriptor::LUIAtlasDescriptor() : 10 | _tex(nullptr) 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /source/luiAtlasDescriptor.h: -------------------------------------------------------------------------------- 1 | // Filename: luiAtlasDescriptor.h 2 | // Created by: tobspr (30Aug14) 3 | // 4 | 5 | #ifndef LUI_ATLAS_DESCRIPTOR_H 6 | #define LUI_ATLAS_DESCRIPTOR_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | #include "texture.h" 12 | #include "config_lui.h" 13 | 14 | class LUIAtlasPool; 15 | 16 | /** 17 | * @brief Class to store positions in a given atlas 18 | * @details This is a container class to store a reference to a sprite in an 19 | * atlas. It stores a handle to the atlas texture, the size of the sprite 20 | * in the atlas, and the uv start and end coordinates. This is the required 21 | * information to render a sprite from that atlas. 22 | * 23 | * The class is internally used by LUISprite to store the atlas position, 24 | * whenever a texture from the atlas is used. 25 | */ 26 | class EXPCL_LUI LUIAtlasDescriptor { 27 | 28 | // Only the LUIAtlasPool is allowed to create new descriptors 29 | friend class LUIAtlasPool; 30 | LUIAtlasDescriptor(); 31 | 32 | INLINE void set_texture(Texture* tex); 33 | INLINE void set_size(const LVector2& size); 34 | INLINE void set_uv_range(const LTexCoord& uv_begin, const LTexCoord& uv_end); 35 | 36 | public: 37 | 38 | INLINE Texture* get_texture() const; 39 | INLINE const LVector2& get_size() const; 40 | INLINE const LTexCoord& get_uv_begin() const; 41 | INLINE const LTexCoord& get_uv_end() const; 42 | 43 | private: 44 | 45 | Texture* _tex; 46 | LVector2 _size; 47 | LTexCoord _uv_begin; 48 | LTexCoord _uv_end; 49 | 50 | }; 51 | 52 | #include "luiAtlasDescriptor.I" 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /source/luiAtlasPacker.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiAtlasPacker.h" 3 | 4 | /** 5 | * @brief Constructs a new atlas packer 6 | * @details This constructs a new atlas packer. The size controls the size of the 7 | * atlas in pixels. 8 | * 9 | * @param size Size of the atlas in pixels 10 | */ 11 | LUIAtlasPacker::LUIAtlasPacker(size_t size) : _size(size) { 12 | // Allocate memory 13 | values_bitmask = new bool[_size * _size]; 14 | memset(values_bitmask, 0x0, sizeof(bool) * _size * _size); 15 | } 16 | 17 | /** 18 | * @brief Finds a region in the atlas 19 | * @details This attempts to find a place for the given dimensions in the atlas. 20 | * If a region is found, returns the upper left coordinate of the region in 21 | * pixels. If no region was found, (-1, -1) is returned. 22 | * 23 | * @param w Width of the region in pixels 24 | * @param h Height of the region in pixels 25 | * 26 | * @return Either coordinate of the region, or (-1, -1) if no free spot was found 27 | */ 28 | LVector2f LUIAtlasPacker::find_position(size_t w, size_t h) { 29 | 30 | // Region exceeds atlas size 31 | if (w > _size || h > _size) 32 | return LVector2f(-1, -1); 33 | 34 | size_t search_w = _size - w; 35 | size_t search_h = _size - h; 36 | 37 | size_t step_size = 1; 38 | 39 | // Less accuracy when the atlas gets bigger 40 | if (_size >= 4096) step_size = 2; 41 | if (_size >= 8192) step_size = 4; 42 | 43 | // Iterate over every pixel (brute force) 44 | for (size_t search_y = 0; search_y <= search_h; search_y += step_size) { 45 | for (size_t search_x = 0; search_x <= search_w; search_x += step_size) { 46 | 47 | // If the pixel is free 48 | if (!get_value(search_x, search_y)) { 49 | 50 | // Possible match, check if the given region would fit in there 51 | bool any_found = false; 52 | for (size_t offs_x = 0; offs_x < w && !any_found; offs_x ++) { 53 | for (size_t offs_y = 0; offs_y < h && !any_found; offs_y ++) { 54 | if (get_value(search_x+offs_x, search_y+offs_y)) { 55 | any_found = true; 56 | break; 57 | } 58 | } 59 | } 60 | 61 | // If no pixel in the region was taken, we found a place to store the region 62 | if (!any_found) { 63 | 64 | // Mark pixels as used 65 | for (size_t mark_x = 0; mark_x < w; ++mark_x) { 66 | for (size_t mark_y = 0; mark_y < h; ++mark_y) { 67 | set_value(search_x + mark_x, search_y + mark_y, true); 68 | } 69 | } 70 | return LVector2f(search_x, search_y); 71 | } 72 | } 73 | } 74 | } 75 | 76 | return LVector2f(-1, -1); 77 | } 78 | 79 | /** 80 | * @brief Destructor 81 | * @details Destructs the atlas packer, freeing all used resources 82 | */ 83 | LUIAtlasPacker::~LUIAtlasPacker() { 84 | delete [] values_bitmask; 85 | } 86 | -------------------------------------------------------------------------------- /source/luiAtlasPacker.h: -------------------------------------------------------------------------------- 1 | // Filename: luiAtlasPacker.h 2 | // Created by: tobspr (30Aug14) 3 | // 4 | 5 | #ifndef LUI_ATLAS_PACKER_H 6 | #define LUI_ATLAS_PACKER_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "lvector2.h" 11 | #include "config_lui.h" 12 | #include "referenceCount.h" 13 | 14 | /** 15 | * @brief Helper class used by the LUIAtlasPacker 16 | * @details This is a helper class which is used by the LUIAtlasPacker to generate 17 | * an atlas. It provides functionality to find positions for sprites in a texture. 18 | * 19 | */ 20 | class EXPCL_LUI LUIAtlasPacker : public ReferenceCount { 21 | 22 | PUBLISHED: 23 | 24 | LUIAtlasPacker(size_t size); 25 | ~LUIAtlasPacker(); 26 | 27 | LVector2f find_position(size_t w, size_t h); 28 | 29 | private: 30 | 31 | // Helper methods to access the interleaved array 32 | INLINE bool get_value(size_t x, size_t y) const { return values_bitmask[x + y * _size]; } 33 | INLINE void set_value(size_t x, size_t y, bool flag) { values_bitmask[x + y * _size] = flag; } 34 | 35 | bool* values_bitmask; 36 | size_t _size; 37 | 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /source/luiAtlasPool.I: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @brief Checks whether an atlas exists 4 | * @details This method checks if there was an atlas loaded with the given name. 5 | * If this is the case, the method returns true, otherwise false. 6 | * 7 | * @param atlas_id Name of the atlas, case sensitive 8 | * @return true if the atlas was loaded, false otherwise 9 | */ 10 | INLINE bool LUIAtlasPool::has_atlas(const string& atlas_id) const { 11 | return _atlases.count(atlas_id) > 0; 12 | } 13 | 14 | /** 15 | * @brief Returns an atlas by name 16 | * @details This method returns an atlas with the given name. If the name was 17 | * not found, because the atlas was not loaded yet, null is returned. 18 | * 19 | * @param atlas_id Name of the atlas 20 | * @return Handle to the atlas, or null 21 | */ 22 | INLINE PT(LUIAtlas) LUIAtlasPool::get_atlas(const string& atlas_id) const { 23 | auto it = _atlases.find(atlas_id); 24 | if (it != _atlases.end()) { 25 | return it->second; 26 | } 27 | return nullptr; 28 | } 29 | 30 | /** 31 | * @brief Returns a descriptor from a given atlas 32 | * @details This returns a descriptor with the given name from the given atlas. 33 | * If there is no atlas with the given name, or no entry in that in that atlas 34 | * exists, an error is printed, and an assertion is raised. 35 | * 36 | * The descriptor contains information about the atlas texture, size, and the 37 | * uv position of the referenced sprite. 38 | * 39 | * @param atlas_id Name of the atlas 40 | * @param entry_id Name of the entry 41 | * 42 | * @return Descriptor of the sprite 43 | */ 44 | INLINE LUIAtlasDescriptor LUIAtlasPool::get_descriptor(const string& atlas_id, const string& entry_id) const { 45 | if (!has_atlas(atlas_id)) { 46 | lui_cat.error() << "Atlas '" << atlas_id << "' not found!" << endl; 47 | nassertr(false, LUIAtlasDescriptor()); 48 | } 49 | 50 | LUIAtlas* atlas = get_atlas(atlas_id); 51 | const LUIAtlasEntry& entry = atlas->get_entry(entry_id); 52 | 53 | LUIAtlasDescriptor descriptor; 54 | descriptor.set_size(entry.size); 55 | descriptor.set_uv_range( 56 | entry.pos / float(atlas->get_size()), 57 | (entry.pos + entry.size) / float(atlas->get_size()) ); 58 | descriptor.set_texture(atlas->get_texture()); 59 | return descriptor; 60 | } 61 | -------------------------------------------------------------------------------- /source/luiAtlasPool.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiAtlasPool.h" 3 | 4 | LUIAtlasPool* LUIAtlasPool::_global_ptr = nullptr; 5 | 6 | /** 7 | * @brief Constructs the LUIAtlasPool 8 | * @details This is the private constructor used to construct the global singleton 9 | */ 10 | LUIAtlasPool::LUIAtlasPool() { 11 | } 12 | 13 | /** 14 | * @brief Returns the global LUIAtlasPool instance 15 | * @details This returns the global instance of the LUIAtlasPool. If no instance 16 | * exists yet, it is created first. 17 | * @return Handle to the global atlas pool instance 18 | */ 19 | LUIAtlasPool* LUIAtlasPool::get_global_ptr() { 20 | if (_global_ptr == nullptr) { 21 | _global_ptr = new LUIAtlasPool(); 22 | } 23 | return _global_ptr; 24 | } 25 | 26 | /** 27 | * @brief Loads an atlas from a given filename and descriptor path 28 | * @details This loads an atlas with the given name from two files, the descriptor 29 | * and texture file. The files should be the ones generated with LUIAtlasGen. 30 | * 31 | * The atlas_desc_path path should point to the file which stores the atlas 32 | * entries, in most cases atlas.txt. The atlas_tex_path should point to the 33 | * atlas texture file, in most cases atlas.png. 34 | * 35 | * In case the atlas fails to load, an error message is printed and nothing 36 | * happens. 37 | * 38 | * @param atlas_id Name of the atlas, under which it will be stored 39 | * @param atlas_desc_path Path to the descriptor file 40 | * @param atlas_tex_path Path to the atlas texture file 41 | */ 42 | void LUIAtlasPool::load_atlas(const string& atlas_id, const string& atlas_desc_path, const string& atlas_tex_path) { 43 | 44 | if (_atlases.count(atlas_id) != 0) { 45 | lui_cat.error() << "Error whilst loading atlas '" << atlas_id << "'" << endl; 46 | lui_cat.error() << "You cannot load multiple atlases with the same name!" << endl; 47 | return; 48 | } 49 | 50 | PT(LUIAtlas) atlas = new LUIAtlas(); 51 | 52 | if (!atlas->load_descriptor_file(atlas_desc_path)) { 53 | lui_cat.error() << "Atlas '" << atlas_id << "' failed to load descriptor." << endl; 54 | return; 55 | } 56 | 57 | if (!atlas->load_texture(atlas_tex_path)) { 58 | lui_cat.error() << "Atlas '" << atlas_id << "' failed to load texture." << endl; 59 | return; 60 | } 61 | 62 | _atlases[atlas_id] = atlas; 63 | } 64 | -------------------------------------------------------------------------------- /source/luiAtlasPool.h: -------------------------------------------------------------------------------- 1 | // Filename: luiAtlasPool.h 2 | // Created by: tobspr (30Aug14) 3 | // 4 | 5 | #ifndef LUI_ATLAS_POOL_H 6 | #define LUI_ATLAS_POOL_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | #include "referenceCount.h" 12 | #include "filename.h" 13 | 14 | #include "luiAtlas.h" 15 | #include "luiAtlasDescriptor.h" 16 | 17 | #include "config_lui.h" 18 | 19 | /** 20 | * @brief Globals storage for multiple atlases 21 | * @details This class stores all atlases, and keeps a reference to them. It also 22 | * provides methods to get a descriptor from a given entry name and atlas name. 23 | */ 24 | class EXPCL_LUI LUIAtlasPool { 25 | 26 | PUBLISHED: 27 | 28 | static LUIAtlasPool* get_global_ptr(); 29 | 30 | void load_atlas(const string& atlas_id, const string& atlas_desc_path, const string& atlas_tex_path); 31 | 32 | INLINE bool has_atlas(const string& atlas_id) const; 33 | INLINE PT(LUIAtlas) get_atlas(const string& atlas_id) const; 34 | INLINE LUIAtlasDescriptor get_descriptor(const string& atlas_id, const string& entry_id) const; 35 | 36 | private: 37 | 38 | LUIAtlasPool(); 39 | pmap _atlases; 40 | static LUIAtlasPool* _global_ptr; 41 | }; 42 | 43 | #include "luiAtlasPool.I" 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /source/luiBaseLayout.I: -------------------------------------------------------------------------------- 1 | 2 | 3 | INLINE void LUIBaseLayout::set_spacing(float spacing) { 4 | _spacing = spacing; 5 | } 6 | 7 | INLINE float LUIBaseLayout::get_spacing() const { 8 | return _spacing; 9 | } 10 | -------------------------------------------------------------------------------- /source/luiBaseLayout.h: -------------------------------------------------------------------------------- 1 | // Filename: luiBaseLayout.h 2 | // Created by: tobspr (06Feb16) 3 | // 4 | 5 | #ifndef LUI_BASE_LAYOUT_H 6 | #define LUI_BASE_LAYOUT_H 7 | 8 | #include "config_lui.h" 9 | #include "luiBaseElement.h" 10 | #include "luiObject.h" 11 | #include "pandabase.h" 12 | 13 | NotifyCategoryDecl(luiBaseLayout, EXPCL_LUI, EXPTP_LUI); 14 | 15 | class EXPCL_LUI LUIBaseLayout : public LUIObject { 16 | public: 17 | 18 | enum CellMode { 19 | CM_fit, // Key: '?' 20 | CM_percentage, // Key: "xxx%", e.g. "23%" 21 | CM_fill, // Key: '*' 22 | CM_fixed, // Key: '10' (absolute value) 23 | }; 24 | 25 | LUIBaseLayout(PyObject* self); 26 | 27 | PUBLISHED: 28 | void add(PT(LUIBaseElement) object, const string& cell_mode = "?"); 29 | void add(PT(LUIBaseElement) object, float cell_height); 30 | void reset(); 31 | void remove_cell(size_t index); 32 | 33 | PT(LUIObject) cell(const string& cell_mode); 34 | PT(LUIObject) cell(float cell_height); 35 | PT(LUIObject) cell(); 36 | 37 | INLINE void set_spacing(float spacing); 38 | INLINE float get_spacing() const; 39 | 40 | MAKE_PROPERTY(spacing ,get_spacing, set_spacing); 41 | 42 | public: 43 | 44 | void update_dimensions_upstream(); 45 | void update_downstream(); 46 | 47 | protected: 48 | struct Cell { 49 | // Cell mode, determines the cell size 50 | CellMode mode; 51 | 52 | // Stores stuff like percentage, pixels, content depends on mode 53 | double payload; 54 | 55 | // Container node 56 | LUIBaseElement* node; 57 | }; 58 | 59 | LUIObject* add_cell(PT(LUIBaseElement) object, Cell cell); 60 | 61 | // Interface 62 | virtual void init_container(LUIObject* container) = 0; 63 | 64 | // Interface to set the metrics, for a horizontal layout the metric 65 | // is the element width, for a vertical layout it is the height. 66 | virtual float get_metric(LUIBaseElement* element) = 0; 67 | virtual void set_metric(LUIBaseElement* element, float metric) = 0; 68 | virtual void set_offset(LUIBaseElement* element, float offset) = 0; 69 | virtual bool has_space(LUIBaseElement* element) = 0; 70 | virtual void set_full_metric(LUIBaseElement* element) = 0; 71 | virtual void clear_metric(LUIBaseElement* element) = 0; 72 | 73 | void update_layout(); 74 | 75 | Cell construct_cell(const string& cell_mode); 76 | pvector _cells; 77 | float _spacing; 78 | 79 | public: 80 | static TypeHandle get_class_type() { 81 | return _type_handle; 82 | } 83 | static void init_type() { 84 | LUIObject::init_type(); 85 | register_type(_type_handle, "LUIBaseLayout", LUIObject::get_class_type()); 86 | } 87 | virtual TypeHandle get_type() const { 88 | return get_class_type(); 89 | } 90 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 91 | 92 | private: 93 | static TypeHandle _type_handle; 94 | }; 95 | 96 | #include "luiBaseLayout.I" 97 | 98 | #endif // LUI_BASE_LAYOUT_H 99 | -------------------------------------------------------------------------------- /source/luiBounds.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE float LUIBounds::get_top() const { 3 | return _bounds.get_x(); 4 | } 5 | 6 | INLINE float LUIBounds::get_right() const { 7 | return _bounds.get_y(); 8 | } 9 | 10 | INLINE float LUIBounds::get_bottom() const { 11 | return _bounds.get_z(); 12 | } 13 | 14 | INLINE float LUIBounds::get_left() const { 15 | return _bounds.get_w(); 16 | } 17 | 18 | INLINE void LUIBounds::set_top(float top) { 19 | _bounds.set_x(top); 20 | } 21 | 22 | INLINE void LUIBounds::set_right(float right) { 23 | _bounds.set_y(right); 24 | } 25 | 26 | INLINE void LUIBounds::set_bottom(float bottom) { 27 | _bounds.set_z(bottom); 28 | } 29 | 30 | INLINE void LUIBounds::set_left(float left) { 31 | _bounds.set_w(left); 32 | } 33 | 34 | INLINE void LUIBounds::set_bounds(const LVector4& bounds) { 35 | _bounds = LVector4(bounds); 36 | } 37 | 38 | INLINE void LUIBounds::set_bounds(float top, float right, float bottom, float left) { 39 | _bounds.set_x(top); 40 | _bounds.set_y(right); 41 | _bounds.set_z(bottom); 42 | _bounds.set_w(left); 43 | } 44 | 45 | INLINE const LVector4& LUIBounds::get_bounds() const { 46 | return _bounds; 47 | } 48 | -------------------------------------------------------------------------------- /source/luiBounds.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiBounds.h" 3 | -------------------------------------------------------------------------------- /source/luiBounds.h: -------------------------------------------------------------------------------- 1 | // Filename: luiBounds.h 2 | // Created by: tobspr (20Sep14) 3 | // 4 | 5 | #ifndef LUI_BOUNDS_H 6 | #define LUI_BOUNDS_H 7 | 8 | #include "config_lui.h" 9 | #include "pandabase.h" 10 | #include "pandasymbols.h" 11 | #include "luse.h" 12 | #include "referenceCount.h" 13 | 14 | class EXPCL_LUI LUIBounds { 15 | 16 | PUBLISHED: 17 | 18 | LUIBounds() : _bounds(-1) {}; 19 | explicit LUIBounds(float fill_value) : _bounds(fill_value) {}; 20 | explicit LUIBounds(const LVector4& bounds) : _bounds(bounds) {}; 21 | LUIBounds(float top, float right, float bottom, float left) 22 | : _bounds(top, right, bottom, left) {}; 23 | 24 | INLINE float get_top() const; 25 | INLINE float get_right() const; 26 | INLINE float get_bottom() const; 27 | INLINE float get_left() const; 28 | 29 | INLINE void set_top(float top); 30 | INLINE void set_right(float right); 31 | INLINE void set_bottom(float bottom); 32 | INLINE void set_left(float left); 33 | 34 | INLINE void set_bounds(const LVector4& bounds); 35 | INLINE void set_bounds(float top, float right, float bottom, float left); 36 | 37 | INLINE const LVector4& get_bounds() const; 38 | 39 | MAKE_PROPERTY(top, get_top, set_top); 40 | MAKE_PROPERTY(right, get_right, set_right); 41 | MAKE_PROPERTY(bottom, get_bottom, set_bottom); 42 | MAKE_PROPERTY(left, get_left, set_left); 43 | 44 | friend ostream& operator<<(ostream& stream, const LUIBounds& bounds) { 45 | return stream << "Bounds[" << bounds.get_top() << ", " << bounds.get_right() << ", " 46 | << bounds.get_bottom() << ", " << bounds.get_left() << "]"; 47 | } 48 | protected: 49 | 50 | LVector4 _bounds; 51 | }; 52 | 53 | 54 | INLINE bool operator==(const LUIBounds& a, const LUIBounds& b) { return a.get_bounds() == b.get_bounds(); } 55 | INLINE bool operator!=(const LUIBounds& a, const LUIBounds& b) { return !(a == b); } 56 | 57 | 58 | #include "luiBounds.I" 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /source/luiChunkDescriptor.I: -------------------------------------------------------------------------------- 1 | 2 | 3 | INLINE int LUIChunkDescriptor::get_slot() const { 4 | return _slot; 5 | } 6 | INLINE LUIVertexChunk* LUIChunkDescriptor::get_chunk() const { 7 | return _chunk; 8 | } 9 | 10 | INLINE void LUIChunkDescriptor::set_slot(int slot) { 11 | _slot = slot; 12 | } 13 | INLINE void LUIChunkDescriptor::set_chunk(LUIVertexChunk* chunk) { 14 | _chunk = chunk; 15 | } 16 | -------------------------------------------------------------------------------- /source/luiChunkDescriptor.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiChunkDescriptor.h" 3 | #include "luiVertexChunk.h" 4 | 5 | void LUIChunkDescriptor::release() { 6 | if (lui_cat.is_spam()) { 7 | lui_cat.spam() << "LuiChunkDescriptor: Releasing slot .. " << endl; 8 | } 9 | _chunk->free_slot(_slot); 10 | } 11 | 12 | void* LUIChunkDescriptor::get_write_ptr() const { 13 | return _chunk->get_slot_ptr(_slot); 14 | } 15 | 16 | LUIChunkDescriptor::LUIChunkDescriptor() { 17 | if (lui_cat.is_spam()) { 18 | lui_cat.spam() << "Constructed new chunk descriptor" << endl; 19 | } 20 | } 21 | 22 | LUIChunkDescriptor::~LUIChunkDescriptor() { 23 | if (lui_cat.is_spam()) { 24 | lui_cat.spam() << "Destructed chunk descriptor" << endl; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source/luiChunkDescriptor.h: -------------------------------------------------------------------------------- 1 | // Filename: luiVertexPool.h 2 | // Created by: tobspr (28Aug14) 3 | // 4 | 5 | 6 | #ifndef LUI_CHUNK_DESCRIPTOR_H 7 | #define LUI_CHUNK_DESCRIPTOR_H 8 | 9 | #include "pandabase.h" 10 | #include "pandasymbols.h" 11 | 12 | class LUIVertexChunk; 13 | 14 | class LUIChunkDescriptor { 15 | 16 | // Give only LUIVertexPool the permission to set the initial values 17 | friend class LUIVertexPool; 18 | 19 | private: 20 | 21 | LUIChunkDescriptor(); 22 | 23 | INLINE void set_slot(int slot); 24 | INLINE void set_chunk(LUIVertexChunk* chunk); 25 | 26 | LUIVertexChunk* _chunk; 27 | int _slot; 28 | 29 | public: 30 | 31 | ~LUIChunkDescriptor(); 32 | 33 | void release(); 34 | void* get_write_ptr() const; 35 | INLINE int get_slot() const; 36 | INLINE LUIVertexChunk* get_chunk() const; 37 | }; 38 | 39 | 40 | #include "luiChunkDescriptor.I" 41 | 42 | 43 | 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /source/luiColorable.I: -------------------------------------------------------------------------------- 1 | 2 | 3 | INLINE void LUIColorable::set_color(const LColor& color) { 4 | _color = color; 5 | } 6 | 7 | INLINE void LUIColorable::set_color(const LVecBase3& rgb) { 8 | _color.set_x(rgb.get_x()); 9 | _color.set_y(rgb.get_y()); 10 | _color.set_z(rgb.get_z()); 11 | } 12 | 13 | INLINE void LUIColorable::set_color(float r, float g, float b, float a) { 14 | _color.set(r, g, b, a); 15 | } 16 | 17 | INLINE void LUIColorable::set_red(float r) { 18 | _color.set_x(r); 19 | } 20 | 21 | INLINE void LUIColorable::set_green(float g) { 22 | _color.set_y(g); 23 | } 24 | 25 | INLINE void LUIColorable::set_blue(float b) { 26 | _color.set_z(b); 27 | } 28 | 29 | INLINE void LUIColorable::set_alpha(float a) { 30 | _color.set_w(a); 31 | } 32 | 33 | INLINE float LUIColorable::get_red() const { 34 | return _color.get_x(); 35 | } 36 | 37 | INLINE float LUIColorable::get_green() const { 38 | return _color.get_y(); 39 | } 40 | 41 | INLINE float LUIColorable::get_blue() const { 42 | return _color.get_z(); 43 | } 44 | 45 | INLINE float LUIColorable::get_alpha() const { 46 | return _color.get_w(); 47 | } 48 | 49 | INLINE const LColor& LUIColorable::get_color() const { 50 | return _color; 51 | } 52 | 53 | INLINE const LColor& LUIColorable::get_composed_color() const { 54 | return _composed_color; 55 | } 56 | 57 | INLINE void LUIColorable::compose_color(const LColor& parent_color) { 58 | _composed_color = LColor( 59 | parent_color.get_x() * _color.get_x(), 60 | parent_color.get_y() * _color.get_y(), 61 | parent_color.get_z() * _color.get_z(), 62 | parent_color.get_w() * _color.get_w() 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /source/luiColorable.cxx: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "luiColorable.h" 4 | 5 | LUIColorable::LUIColorable() : _color(1), _composed_color(1) { 6 | } 7 | 8 | LUIColorable::~LUIColorable() { 9 | } 10 | -------------------------------------------------------------------------------- /source/luiColorable.h: -------------------------------------------------------------------------------- 1 | // Filename: luiColorable.h 2 | // Created by: tobspr (19Sep14) 3 | // 4 | 5 | #ifndef LUI_COLORABLE_H 6 | #define LUI_COLORABLE_H 7 | 8 | #include "config_lui.h" 9 | #include "pandabase.h" 10 | #include "pandasymbols.h" 11 | #include "luse.h" 12 | 13 | class EXPCL_LUI LUIColorable { 14 | 15 | PUBLISHED: 16 | 17 | // Color 18 | INLINE void set_color(const LColor& color); 19 | INLINE void set_color(const LVecBase3& rgb); 20 | INLINE void set_color(float r, float g, float b, float a = 1.0); 21 | 22 | INLINE void set_red(float r); 23 | INLINE void set_green(float g); 24 | INLINE void set_blue(float b); 25 | INLINE void set_alpha(float a); 26 | 27 | INLINE float get_red() const; 28 | INLINE float get_green() const; 29 | INLINE float get_blue() const; 30 | INLINE float get_alpha() const; 31 | 32 | INLINE const LColor& get_color() const; 33 | INLINE const LColor& get_composed_color() const; 34 | 35 | // Python properties 36 | MAKE_PROPERTY(color, get_color, set_color); 37 | MAKE_PROPERTY(composed_color, get_composed_color); 38 | MAKE_PROPERTY(red, get_red, set_red); 39 | MAKE_PROPERTY(green, get_green, set_green); 40 | MAKE_PROPERTY(blue, get_blue, set_blue); 41 | MAKE_PROPERTY(alpha, get_alpha, set_alpha); 42 | 43 | protected: 44 | 45 | LUIColorable(); 46 | virtual ~LUIColorable(); 47 | 48 | INLINE void compose_color(const LColor& parent_color = LColor(1)); 49 | 50 | LColor _color; 51 | LColor _composed_color; 52 | }; 53 | 54 | #include "luiColorable.I" 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /source/luiEventData.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE string LUIEventData::get_name() const { 3 | return _event_name; 4 | } 5 | 6 | INLINE PT(LUIBaseElement) LUIEventData::get_sender() const { 7 | return _sender; 8 | } 9 | 10 | INLINE LPoint2 LUIEventData::get_coordinates() const { 11 | return _coordinates; 12 | } 13 | 14 | INLINE wstring LUIEventData::get_message() const { 15 | return _message; 16 | } 17 | 18 | INLINE size_t LUIEventData::get_key_modifiers() const { 19 | return _key_modifiers; 20 | } 21 | 22 | INLINE bool LUIEventData::get_modifier_state(KeyModifiers modifier) const { 23 | return (_key_modifiers & modifier) != 0; 24 | } 25 | 26 | INLINE bool LUIEventData::get_modifier_state(const string& modifier_name) const { 27 | if (modifier_name == "alt") { 28 | return get_modifier_state(KM_alt); 29 | } else if (modifier_name == "shift") { 30 | return get_modifier_state(KM_shift); 31 | } else if (modifier_name == "ctrl") { 32 | return get_modifier_state(KM_ctrl); 33 | } 34 | 35 | lui_cat.error() << "Invalid key modifier name: '" << modifier_name << "'" << endl; 36 | return false; 37 | } 38 | -------------------------------------------------------------------------------- /source/luiEventData.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiEventData.h" 3 | 4 | TypeHandle LUIEventData::_type_handle; 5 | 6 | LUIEventData::LUIEventData(LUIBaseElement* sender, const string& event_name, 7 | const wstring& message, const LPoint2& coordinates, 8 | size_t key_modifiers) 9 | : CallbackData(), 10 | _event_name(event_name), 11 | _sender(sender), 12 | _coordinates(coordinates), 13 | _message(message), 14 | _key_modifiers(key_modifiers) { 15 | } 16 | 17 | LUIEventData::~LUIEventData() { 18 | } 19 | -------------------------------------------------------------------------------- /source/luiEventData.h: -------------------------------------------------------------------------------- 1 | // Filename: luiEventData.h 2 | // Created by: tobspr (17Sep14) 3 | // 4 | 5 | #ifndef LUI_EVENT_DATA_H 6 | #define LUI_EVENT_DATA_H 7 | 8 | #include "config_lui.h" 9 | #include "pandabase.h" 10 | #include "pandasymbols.h" 11 | #include "luse.h" 12 | #include "referenceCount.h" 13 | #include "callbackData.h" 14 | #include "luiBaseElement.h" 15 | 16 | class EXPCL_LUI LUIEventData : public CallbackData, public ReferenceCount { 17 | 18 | PUBLISHED: 19 | 20 | // All available key modifiers 21 | enum KeyModifiers { 22 | KM_shift = 1, 23 | KM_alt = 2, 24 | KM_ctrl = 4 25 | }; 26 | 27 | 28 | INLINE string get_name() const; 29 | INLINE PT(LUIBaseElement) get_sender() const; 30 | INLINE LPoint2 get_coordinates() const; 31 | INLINE wstring get_message() const; 32 | INLINE size_t get_key_modifiers() const; 33 | 34 | // Same as getModifierState in JS 35 | INLINE bool get_modifier_state(KeyModifiers modifier) const; 36 | INLINE bool get_modifier_state(const string& modifier_name) const; 37 | 38 | MAKE_PROPERTY(name, get_name); 39 | MAKE_PROPERTY(sender, get_sender); 40 | MAKE_PROPERTY(coordinates, get_coordinates); 41 | MAKE_PROPERTY(message, get_message); 42 | MAKE_PROPERTY(key_modifiers, get_key_modifiers); 43 | 44 | public: 45 | 46 | LUIEventData(LUIBaseElement* sender, 47 | const string& event_name, 48 | const wstring& message, 49 | const LPoint2& coordinates = LPoint2(0), 50 | size_t key_modifiers = 0); 51 | ~LUIEventData(); 52 | 53 | protected: 54 | 55 | string _event_name; 56 | size_t _key_modifiers; 57 | wstring _message; 58 | PT(LUIBaseElement) _sender; 59 | LPoint2 _coordinates; 60 | 61 | public: 62 | static TypeHandle get_class_type() { 63 | return _type_handle; 64 | } 65 | static void init_type() { 66 | CallbackData::init_type(); 67 | register_type(_type_handle, "LUIEventData", CallbackData::get_class_type()); 68 | } 69 | virtual TypeHandle get_type() const { 70 | return get_class_type(); 71 | } 72 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 73 | 74 | private: 75 | static TypeHandle _type_handle; 76 | 77 | }; 78 | 79 | 80 | #include "luiEventData.I" 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /source/luiExpression.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE bool LUIExpression::has_expression() const { 3 | return _type != ET_none; 4 | } 5 | 6 | INLINE bool LUIExpression::has_fixed_expression() const { 7 | return _type == ET_scalar; 8 | } 9 | 10 | INLINE bool LUIExpression::has_parent_dependent_expression() const { 11 | return _type == ET_percentage; 12 | } 13 | 14 | INLINE void LUIExpression::clear() { 15 | _type = ET_none; 16 | _value = 0.0f; 17 | } 18 | -------------------------------------------------------------------------------- /source/luiExpression.cxx: -------------------------------------------------------------------------------- 1 | #include "luiExpression.h" 2 | 3 | #include "pstrtod.h" 4 | 5 | 6 | NotifyCategoryDef(luiExpression, ":lui"); 7 | 8 | 9 | LUIExpression::LUIExpression() : _type(ET_none), _value(0.0f) { 10 | } 11 | 12 | void LUIExpression::load_expression(float scalar) { 13 | if (scalar < 0.0f) { 14 | _type = ET_none; 15 | _value = 0.0f; 16 | } else { 17 | _type = ET_scalar; 18 | _value = scalar; 19 | } 20 | } 21 | 22 | void LUIExpression::load_expression(const string& str) { 23 | if (str.size() < 2) { 24 | luiExpression_cat.error() << "String '" << str << "' is no valid expression!" << endl; 25 | return; 26 | } 27 | 28 | if (str.back() != '%') { 29 | luiExpression_cat.error() << "String '" << str << "' is not a valid percentage!" << endl; 30 | return; 31 | } 32 | 33 | string val = str.substr(0, str.size() - 1); 34 | 35 | char* endptr; 36 | double d_val = pstrtod(val.c_str(), &endptr); 37 | 38 | if (*endptr != 0) { 39 | luiExpression_cat.error() << "Could not parse float '" << val << "'" << endl; 40 | return; 41 | } 42 | _value = (float)(d_val / 100.0f); 43 | _type = ET_percentage; 44 | } 45 | 46 | float LUIExpression::evaluate(float max_constraint) const { 47 | // cout << "Evaluating expression, max constraint = " << max_constraint << ", value = " << _value << ", type = " << _type << endl; 48 | switch(_type) { 49 | case ET_none: 50 | return 0; 51 | case ET_scalar: 52 | return _value; 53 | case ET_percentage: 54 | return _value * max_constraint; 55 | } 56 | nassertr(false, 0.0f); // Should never happen 57 | return -1; 58 | } 59 | -------------------------------------------------------------------------------- /source/luiExpression.h: -------------------------------------------------------------------------------- 1 | // Filename: luiExpression.h 2 | // Created by: tobspr (31Jan16) 3 | // 4 | 5 | #ifndef LUI_EXPRESSION_H 6 | #define LUI_EXPRESSION_H 7 | 8 | #include "config_lui.h" 9 | #include "pandabase.h" 10 | 11 | NotifyCategoryDecl(luiExpression, EXPCL_LUI, EXPTP_LUI); 12 | 13 | class EXPCL_LUI LUIExpression { 14 | public: 15 | enum ExpressionType { 16 | ET_none, // No type 17 | ET_scalar, // Simple scalar, like 10, in pixels 18 | ET_percentage, // Percentage value, like 20% 19 | }; 20 | 21 | LUIExpression(); 22 | void load_expression(float scalar); 23 | void load_expression(const string& str); 24 | void clear(); 25 | float evaluate(float max_constraint) const; 26 | 27 | INLINE bool has_expression() const; 28 | INLINE bool has_fixed_expression() const; 29 | INLINE bool has_parent_dependent_expression() const; 30 | 31 | private: 32 | ExpressionType _type; 33 | float _value; 34 | }; 35 | 36 | inline ostream& operator<<(ostream& stream, LUIExpression::ExpressionType ty) { 37 | switch(ty) { 38 | case LUIExpression::ET_none: return stream << "ET_none"; 39 | case LUIExpression::ET_scalar: return stream << "ET_scalar"; 40 | case LUIExpression::ET_percentage: return stream << "ET_percentage"; 41 | } 42 | return stream << "(Invalid Expression Type)"; 43 | } 44 | 45 | #include "luiExpression.I" 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /source/luiFontPool.I: -------------------------------------------------------------------------------- 1 | 2 | 3 | INLINE bool LUIFontPool::has_font(const string& name) const { 4 | return _fonts.count(name) == 1; 5 | } 6 | 7 | DynamicTextFont* LUIFontPool::get_font(const string& name) const { 8 | nassertr(has_font(name), nullptr); 9 | return _fonts.at(name); 10 | } 11 | -------------------------------------------------------------------------------- /source/luiFontPool.cxx: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "luiFontPool.h" 4 | 5 | 6 | LUIFontPool* LUIFontPool::_global_ptr = nullptr; 7 | 8 | LUIFontPool::LUIFontPool() { 9 | 10 | PT(DynamicTextFont) font = DCAST(DynamicTextFont, TextProperties::get_default_font()); 11 | if (font != nullptr) { 12 | register_font("default", font); 13 | } else { 14 | lui_cat.warning() << "Could not load default font, as it is no dynamic font!" << endl; 15 | } 16 | 17 | } 18 | 19 | LUIFontPool::~LUIFontPool() { 20 | } 21 | 22 | LUIFontPool* LUIFontPool::get_global_ptr() { 23 | if (_global_ptr == nullptr) { 24 | _global_ptr = new LUIFontPool(); 25 | } 26 | return _global_ptr; 27 | } 28 | 29 | void LUIFontPool::register_font(const string& name, PT(DynamicTextFont) font) { 30 | _fonts[name] = font; 31 | if (font->get_num_pages() > 0) { 32 | lui_cat.warning() << "Font was already used, calling clear() first." << endl; 33 | font->clear(); 34 | } 35 | font->set_fg(LColor(0.99, 0.99, 0.99, 1.0)); 36 | } 37 | 38 | void LUIFontPool::load_font(const string& name, const string&font_file) { 39 | lui_cat.error() << "Todo: LUIFontPool::load_font" << endl; 40 | } 41 | -------------------------------------------------------------------------------- /source/luiFontPool.h: -------------------------------------------------------------------------------- 1 | // Filename: luiFontPool.h 2 | // Created by: tobspr (13Sep14) 3 | // 4 | 5 | #ifndef LUI_FONT_POOL_H 6 | #define LUI_FONT_POOL_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | #include "referenceCount.h" 12 | #include "filename.h" 13 | #include "dynamicTextFont.h" 14 | #include "textProperties.h" 15 | #include "dcast.h" 16 | #include "config_lui.h" 17 | 18 | class EXPCL_LUI LUIFontPool { 19 | 20 | PUBLISHED: 21 | 22 | static LUIFontPool* get_global_ptr(); 23 | void load_font(const string& name, const string&font_file); 24 | void register_font(const string& name, PT(DynamicTextFont) font); 25 | INLINE bool has_font(const string& name) const; 26 | INLINE DynamicTextFont* get_font(const string& name) const; 27 | 28 | private: 29 | 30 | LUIFontPool(); 31 | ~LUIFontPool(); 32 | 33 | pmap _fonts; 34 | 35 | static LUIFontPool* _global_ptr; 36 | 37 | }; 38 | 39 | #include "luiFontPool.I" 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /source/luiHorizontalLayout.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiHorizontalLayout.h" 3 | 4 | TypeHandle LUIHorizontalLayout::_type_handle; 5 | NotifyCategoryDef(luiHorizontalLayout, ":lui"); 6 | 7 | 8 | LUIHorizontalLayout::LUIHorizontalLayout(PyObject* self, LUIObject* parent, float spacing) 9 | : LUIBaseLayout(self) { 10 | set_spacing(spacing); 11 | set_parent(parent); 12 | } 13 | 14 | void LUIHorizontalLayout::init_container(LUIObject* container) { 15 | } 16 | 17 | float LUIHorizontalLayout::get_metric(LUIBaseElement* element) { 18 | return element->get_width(); 19 | } 20 | 21 | void LUIHorizontalLayout::set_metric(LUIBaseElement* element, float metric) { 22 | element->set_width(metric); 23 | } 24 | 25 | void LUIHorizontalLayout::set_offset(LUIBaseElement* element, float offset) { 26 | element->set_left(offset); 27 | 28 | // Since we are in the downstream pass when performing this, our children 29 | // won't get the update right in time, so make sure they get it. 30 | // element->move_by(LVector2(offset, 0)); 31 | } 32 | 33 | bool LUIHorizontalLayout::has_space(LUIBaseElement* element) { 34 | return element->has_height(); 35 | } 36 | 37 | void LUIHorizontalLayout::set_full_metric(LUIBaseElement* element) { 38 | element->set_height("100%"); 39 | } 40 | 41 | void LUIHorizontalLayout::clear_metric(LUIBaseElement* element) { 42 | element->clear_height(); 43 | } 44 | -------------------------------------------------------------------------------- /source/luiHorizontalLayout.h: -------------------------------------------------------------------------------- 1 | // Filename: luiHorizontalLayout.h 2 | // Created by: tobspr (31Jan16) 3 | // 4 | 5 | #ifndef LUI_HORIZONTAL_LAYOUT_H 6 | #define LUI_HORIZONTAL_LAYOUT_H 7 | 8 | #include "config_lui.h" 9 | #include "luiBaseLayout.h" 10 | 11 | #include "pandabase.h" 12 | NotifyCategoryDecl(luiHorizontalLayout, EXPCL_LUI, EXPTP_LUI); 13 | 14 | class EXPCL_LUI LUIHorizontalLayout : public LUIBaseLayout { 15 | 16 | PUBLISHED: 17 | LUIHorizontalLayout(PyObject* self, LUIObject* parent, float spacing = 0.0); 18 | 19 | protected: 20 | // Interfaces 21 | void init_container(LUIObject* container); 22 | float get_metric(LUIBaseElement* element); 23 | void set_metric(LUIBaseElement* element, float metric); 24 | void set_offset(LUIBaseElement* element, float offset); 25 | bool has_space(LUIBaseElement* element); 26 | void set_full_metric(LUIBaseElement* element); 27 | void clear_metric(LUIBaseElement* element); 28 | 29 | 30 | public: 31 | static TypeHandle get_class_type() { 32 | return _type_handle; 33 | } 34 | static void init_type() { 35 | LUIBaseLayout::init_type(); 36 | register_type(_type_handle, "LUIHorizontalLayout", LUIBaseLayout::get_class_type()); 37 | } 38 | virtual TypeHandle get_type() const { 39 | return get_class_type(); 40 | } 41 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 42 | 43 | private: 44 | static TypeHandle _type_handle; 45 | 46 | }; 47 | 48 | #endif // LUI_HORIZONTAL_LAYOUT_H 49 | -------------------------------------------------------------------------------- /source/luiInputHandler.I: -------------------------------------------------------------------------------- 1 | 2 | 3 | INLINE bool LUIInputHandler::mouse_key_pressed(int index) const { 4 | nassertr(index >= 0 && index < 5, false); 5 | return _last_state.mouse_buttons[index] == false && _current_state.mouse_buttons[index] == true; 6 | } 7 | 8 | INLINE bool LUIInputHandler::mouse_key_released(int index) const { 9 | nassertr(index >= 0 && index < 5, false); 10 | return _last_state.mouse_buttons[index] == true && _current_state.mouse_buttons[index] == false; 11 | } 12 | 13 | INLINE string LUIInputHandler::get_key_string(int key) const { 14 | auto it = _keymap.find(key); 15 | if (it != _keymap.end()) { 16 | return it->second; 17 | } 18 | return ""; 19 | } 20 | 21 | INLINE wstring LUIInputHandler::get_mouse_button_name(size_t index) const { 22 | return wstring(L"mouse-") + std::to_wstring(static_cast(index)); 23 | } 24 | -------------------------------------------------------------------------------- /source/luiInputHandler.h: -------------------------------------------------------------------------------- 1 | // Filename: luiInputHandler.h 2 | // Created by: tobspr (16Sep14) 3 | // 4 | 5 | #ifndef LUI_INPUT_HANDLER_H 6 | #define LUI_INPUT_HANDLER_H 7 | 8 | #include "config_lui.h" 9 | #include "dataNode.h" 10 | #include "buttonHandle.h" 11 | #include "luiRoot.h" 12 | #include "luiBaseElement.h" 13 | 14 | class LUIBaseElement; 15 | 16 | class EXPCL_LUI LUIInputHandler : public DataNode { 17 | 18 | PUBLISHED: 19 | 20 | LUIInputHandler(const string& name = string()); 21 | virtual ~LUIInputHandler(); 22 | 23 | public: 24 | 25 | // Inherited from DataNode 26 | virtual void do_transmit_data(DataGraphTraverser* trav, 27 | const DataNodeTransmit& input, 28 | DataNodeTransmit& output); 29 | void process(LUIRoot* root); 30 | 31 | protected: 32 | 33 | struct LUIInputState { 34 | LVecBase2 mouse_pos; 35 | bool has_mouse_pos; 36 | bool mouse_buttons[5]; 37 | size_t key_modifiers; 38 | }; 39 | 40 | enum LUIKeyEventMode { 41 | M_up, 42 | M_down, 43 | M_repeat, 44 | M_press 45 | }; 46 | 47 | struct LUIKeyEvent { 48 | string btn_name; 49 | LUIKeyEventMode mode; 50 | }; 51 | 52 | INLINE string get_key_string(int key) const; 53 | INLINE wstring get_mouse_button_name(size_t index) const; 54 | 55 | void trigger_event(LUIBaseElement* sender, const string& name, 56 | const wstring& message = L"") const; 57 | 58 | LUIBaseElement* _hover_element; 59 | vector _mouse_down_elements; 60 | LUIBaseElement* _focused_element; 61 | 62 | int _mouse_pos_input; 63 | int _buttons_input; 64 | 65 | INLINE bool mouse_key_pressed(int index) const; 66 | INLINE bool mouse_key_released(int index) const; 67 | 68 | LUIInputState _last_state; 69 | LUIInputState _current_state; 70 | 71 | pmap _keymap; 72 | vector _key_events; 73 | vector _text_events; 74 | 75 | public: 76 | static TypeHandle get_class_type() { 77 | return _type_handle; 78 | } 79 | static void init_type() { 80 | DataNode::init_type(); 81 | register_type(_type_handle, "LUIInputHandler", 82 | DataNode::get_class_type()); 83 | } 84 | virtual TypeHandle get_type() const { 85 | return get_class_type(); 86 | } 87 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 88 | 89 | private: 90 | static TypeHandle _type_handle; 91 | 92 | }; 93 | 94 | #include "luiInputHandler.I" 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /source/luiIterators.h: -------------------------------------------------------------------------------- 1 | // Filename: luiIterators.h 2 | // Created by: tobspr (01Sep14) 3 | // 4 | 5 | #ifndef LUI_ITERATORS_H 6 | #define LUI_ITERATORS_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "referenceCount.h" 11 | 12 | class LUIBaseElement; 13 | 14 | // Iterators 15 | typedef pvector::const_iterator lui_const_element_iterator; 16 | 17 | class EXPCL_LUI LUIElementIterator : public ReferenceCount { 18 | PUBLISHED: 19 | INLINE LUIBaseElement* __next__() { 20 | if (_iter != _end) { 21 | return *_iter++; 22 | } 23 | return nullptr; 24 | } 25 | INLINE LUIElementIterator& __iter__() { 26 | return *this; 27 | } 28 | public: 29 | LUIElementIterator(lui_const_element_iterator begin, lui_const_element_iterator end) 30 | : _iter(begin), _end(end) { 31 | } 32 | ~LUIElementIterator() { 33 | } 34 | private: 35 | lui_const_element_iterator _iter; 36 | lui_const_element_iterator _end; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /source/luiObject.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE bool lui_compare_z_offset(LUIBaseElement* a, LUIBaseElement* b) { 3 | return a->get_z_offset() < b->get_z_offset(); 4 | } 5 | 6 | INLINE void LUIObject::remove_child(PT(LUIBaseElement) child) { 7 | 8 | if (_content_node) { 9 | return _content_node->remove_child(child); 10 | } 11 | 12 | auto child_it = std::find(_children.begin(), _children.end(), child); 13 | 14 | if (child_it == _children.end()) { 15 | luiObject_cat.warning() << "Attempted to remove child, but child is not attached to this object. Parent = " << _debug_name << ", child = " << child->_debug_name << endl; 16 | return; 17 | } 18 | 19 | if (luiObject_cat.is_spam()) { 20 | luiObject_cat.spam() << "Removing child .." << endl; 21 | } 22 | 23 | _children.erase(child_it); 24 | child->on_detached(); 25 | child->do_set_parent(nullptr); 26 | 27 | if (luiObject_cat.is_spam()) { 28 | luiObject_cat.spam() << "Reference count is now: " << child->get_ref_count() << endl; 29 | } 30 | 31 | } 32 | 33 | INLINE void LUIObject::on_child_z_offset_changed() { 34 | if (!std::is_sorted(_children.cbegin(), _children.cend(), lui_compare_z_offset)) 35 | std::sort(_children.begin(), _children.end(), lui_compare_z_offset); 36 | } 37 | 38 | INLINE void LUIObject::remove_all_children() { 39 | if (luiObject_cat.is_spam()) { 40 | luiObject_cat.spam() << "Removing all children .." << endl; 41 | } 42 | 43 | // Detach all children 44 | for (auto it = _children.begin(); it != _children.end(); ++it) { 45 | (*it)->on_detached(); 46 | (*it)->do_set_parent(nullptr); 47 | } 48 | 49 | // Now clear the vector 50 | _children.clear(); 51 | } 52 | 53 | 54 | INLINE PT(LUIBaseElement) LUIObject::add_child(PT(LUIBaseElement) child) { 55 | if (_content_node) { 56 | return _content_node->add_child(child); 57 | } 58 | 59 | if (child->get_parent()) { 60 | luiObject_cat.error() << "You cannot reattach a child, unattach the child from it's current parent first! target = " << child->_debug_name << endl; 61 | return child; 62 | } 63 | 64 | child->do_set_parent(this); 65 | _children.push_back(child); 66 | 67 | // This has to be last. Otherwise we're attaching to the pool with outdated positions 68 | child->set_root(_root); 69 | 70 | on_child_z_offset_changed(); 71 | 72 | return child; 73 | } 74 | 75 | INLINE PT(LUIElementIterator) LUIObject::get_children() const { 76 | return new LUIElementIterator(_children.begin(), _children.end()); 77 | } 78 | 79 | INLINE PT(LUIBaseElement) LUIObject::get_child(size_t index) const { 80 | nassertr(index < _children.size(), nullptr); 81 | return _children[index]; 82 | } 83 | 84 | INLINE int LUIObject::get_child_count() const { 85 | return _children.size(); 86 | } 87 | 88 | INLINE void LUIObject::on_detached() { 89 | if (luiObject_cat.is_spam()) { 90 | luiObject_cat.spam() << "Got detached .." << endl; 91 | } 92 | 93 | unregister_events(); 94 | _root = nullptr; 95 | _parent = nullptr; 96 | 97 | for (auto it = _children.begin(); it!= _children.end(); ++it) { 98 | (*it)->on_detached(); 99 | } 100 | } 101 | 102 | INLINE void LUIObject::set_content_node(PT(LUIObject) content_node) { 103 | _content_node = content_node; 104 | } 105 | 106 | INLINE PT(LUIObject) LUIObject::get_content_node() const { 107 | return _content_node; 108 | } 109 | -------------------------------------------------------------------------------- /source/luiObject.h: -------------------------------------------------------------------------------- 1 | // Filename: luiNode.h 2 | // Created by: tobspr (28Aug14) 3 | // 4 | 5 | #ifndef LUI_NODE_H 6 | #define LUI_NODE_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "referenceCount.h" 11 | #include "internalName.h" 12 | #include "luse.h" 13 | #include "luiAtlas.h" 14 | #include "luiBaseElement.h" 15 | #include "luiSprite.h" 16 | #include "luiAtlasPool.h" 17 | #include "luiAtlasDescriptor.h" 18 | #include "luiIterators.h" 19 | #include "luiColorable.h" 20 | 21 | #include "config_lui.h" 22 | 23 | class LUISprite; 24 | class LUIRoot; 25 | 26 | NotifyCategoryDecl(luiObject, EXPCL_LUI, EXPTP_LUI); 27 | 28 | class EXPCL_LUI LUIObject : public LUIBaseElement { 29 | 30 | friend class LUIRoot; 31 | 32 | PUBLISHED: 33 | 34 | LUIObject(PyObject* self, float x=0.0f, float y=0.0f, 35 | float w=-1.0f, float h=-1.0f, bool solid=false); 36 | LUIObject(PyObject* self, LUIObject* parent, float x=0.0, float y=0.0, 37 | float w=-1.0f, float h=-1.0f, bool solid=false); 38 | 39 | virtual ~LUIObject(); 40 | 41 | INLINE PT(LUIElementIterator) get_children() const; 42 | INLINE PT(LUIBaseElement) get_child(size_t index) const; 43 | INLINE PT(LUIBaseElement) add_child(PT(LUIBaseElement) child); 44 | INLINE void remove_child(PT(LUIBaseElement) child); 45 | INLINE void remove_all_children(); 46 | INLINE int get_child_count() const; 47 | 48 | INLINE void set_content_node(PT(LUIObject) content_node); 49 | INLINE PT(LUIObject) get_content_node() const; 50 | 51 | virtual void ls(int indent = 0); 52 | 53 | // Python properties 54 | MAKE_PROPERTY(children, get_children); 55 | MAKE_PROPERTY(child_count, get_child_count); 56 | MAKE_PROPERTY(content_node, get_content_node, set_content_node); 57 | 58 | public: 59 | 60 | INLINE void on_child_z_offset_changed(); 61 | void update_downstream(); 62 | void update_upstream(); 63 | void update_clip_bounds(); 64 | void update_dimensions_upstream(); 65 | 66 | void move_by(const LVector2& offset); 67 | 68 | void fit_dimensions(); 69 | 70 | protected: 71 | void update_dimensions(); 72 | void init(); 73 | 74 | // Interface to LUIBaseElement 75 | INLINE virtual void on_detached(); 76 | virtual void set_root(LUIRoot* root); 77 | virtual void render_recursive(bool is_topmost_pass, bool render_anyway); 78 | 79 | pvector _children; 80 | PT(LUIObject) _content_node; 81 | 82 | static int _instance_count; 83 | 84 | public: 85 | static TypeHandle get_class_type() { 86 | return _type_handle; 87 | } 88 | static void init_type() { 89 | LUIBaseElement::init_type(); 90 | register_type(_type_handle, "LUIObject", LUIBaseElement::get_class_type()); 91 | } 92 | virtual TypeHandle get_type() const { 93 | return get_class_type(); 94 | } 95 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 96 | 97 | private: 98 | static TypeHandle _type_handle; 99 | }; 100 | 101 | #include "luiObject.I" 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /source/luiRect.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE float LUIRect::get_x() const { 3 | return _rect.get_x(); 4 | } 5 | 6 | INLINE float LUIRect::get_y() const { 7 | return _rect.get_y(); 8 | } 9 | 10 | INLINE float LUIRect::get_w() const { 11 | return _rect.get_z(); 12 | } 13 | 14 | INLINE float LUIRect::get_h() const { 15 | return _rect.get_w(); 16 | } 17 | 18 | INLINE void LUIRect::set_x(float x) { 19 | _rect.set_x(x); 20 | } 21 | 22 | INLINE void LUIRect::set_y(float y) { 23 | _rect.set_y(y); 24 | } 25 | 26 | INLINE void LUIRect::set_w(float w) { 27 | _rect.set_z(w); 28 | } 29 | 30 | INLINE void LUIRect::set_h(float h) { 31 | _rect.set_w(h); 32 | } 33 | 34 | INLINE void LUIRect::set_rect(const LVector4& rect) { 35 | _rect = rect; 36 | } 37 | 38 | INLINE void LUIRect::set_rect(const LVector2& xy, const LVector2& wh) { 39 | _rect.set(xy.get_x(), xy.get_y(), wh.get_x(), wh.get_y()); 40 | } 41 | 42 | INLINE void LUIRect::set_rect(float x, float y, float w, float h) { 43 | _rect.set(x, y, w, h); 44 | } 45 | 46 | INLINE const LVector4& LUIRect::get_rect() const { 47 | return _rect; 48 | } 49 | 50 | INLINE LVector2 LUIRect::get_xy() const { 51 | return LVector2(_rect.get_x(), _rect.get_y()); 52 | } 53 | 54 | INLINE LVector2 LUIRect::get_wh() const { 55 | return LVector2(_rect.get_z(), _rect.get_w()); 56 | } 57 | -------------------------------------------------------------------------------- /source/luiRect.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiRect.h" 3 | 4 | -------------------------------------------------------------------------------- /source/luiRect.h: -------------------------------------------------------------------------------- 1 | // Filename: luiRect.h 2 | // Created by: tobspr (22Sep14) 3 | // 4 | 5 | #ifndef LUI_RECT_H 6 | #define LUI_RECT_H 7 | 8 | #include "config_lui.h" 9 | #include "pandabase.h" 10 | #include "pandasymbols.h" 11 | #include "luse.h" 12 | #include "referenceCount.h" 13 | 14 | class EXPCL_LUI LUIRect { 15 | 16 | PUBLISHED: 17 | LUIRect() : _rect(-1) {}; 18 | explicit LUIRect(const LVector4& rect) : _rect(rect) {}; 19 | LUIRect(float x, float y, float w, float h) : _rect(x, y, w, h) {}; 20 | 21 | INLINE float get_x() const; 22 | INLINE float get_y() const; 23 | INLINE float get_w() const; 24 | INLINE float get_h() const; 25 | 26 | INLINE LVector2 get_xy() const; 27 | INLINE LVector2 get_wh() const; 28 | 29 | INLINE void set_x(float x); 30 | INLINE void set_y(float y); 31 | INLINE void set_w(float w); 32 | INLINE void set_h(float h); 33 | 34 | INLINE void set_rect(const LVector4& rect); 35 | INLINE void set_rect(const LVector2& xy, const LVector2& wh); 36 | INLINE void set_rect(float x, float y, float w, float h); 37 | 38 | 39 | INLINE const LVector4& get_rect() const; 40 | 41 | MAKE_PROPERTY(x, get_x, set_x); 42 | MAKE_PROPERTY(y, get_y, set_y); 43 | MAKE_PROPERTY(w, get_w, set_w); 44 | MAKE_PROPERTY(h, get_h, set_h); 45 | 46 | friend ostream& operator<<(ostream& stream, const LUIRect& rect) { 47 | return stream << "Rect[" << rect.get_x() << " x " << rect.get_y() << " / " 48 | << rect.get_w() << " x " << rect.get_h() << "]"; 49 | } 50 | 51 | protected: 52 | LVector4 _rect; 53 | }; 54 | 55 | 56 | INLINE bool operator==(const LUIRect& a, const LUIRect& b) { return a.get_rect() == b.get_rect(); } 57 | INLINE bool operator!=(const LUIRect& a, const LUIRect& b) { return !(a == b); } 58 | 59 | #include "luiRect.I" 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /source/luiRegion.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE LUIRegion* LUIRegion:: 3 | make(const string& context_name, GraphicsOutput *window) { 4 | return make(context_name, window, LVecBase4(0.0f, 1.0f, 0.0f, 1.0f)); 5 | } 6 | 7 | 8 | INLINE LUIRegion* LUIRegion:: 9 | make(const string& context_name, GraphicsOutput* window, 10 | const LVecBase4& dimensions) { 11 | return new LUIRegion(window, dimensions, context_name); 12 | } 13 | 14 | INLINE LUIObject* LUIRegion::get_root() const { 15 | return _lui_root->node(); 16 | } 17 | 18 | INLINE void LUIRegion::set_input_handler(LUIInputHandler* handler) { 19 | _input_handler = handler; 20 | } 21 | 22 | INLINE LUIInputHandler* LUIRegion::get_input_handler() const { 23 | return _input_handler; 24 | } 25 | 26 | 27 | INLINE void LUIRegion::set_render_wireframe(bool wireframe) { 28 | _wireframe = wireframe; 29 | } 30 | 31 | INLINE void LUIRegion::toggle_render_wireframe() { 32 | set_render_wireframe(!_wireframe); 33 | } 34 | -------------------------------------------------------------------------------- /source/luiRegion.h: -------------------------------------------------------------------------------- 1 | // Filename: luiRegion.h 2 | // Created by: tobspr (02Sep14) 3 | // 4 | 5 | #ifndef LUI_REGION_H 6 | #define LUI_REGION_H 7 | 8 | 9 | #include "pandabase.h" 10 | #include "pandasymbols.h" 11 | #include "config_lui.h" 12 | #include "camera.h" 13 | #include "displayRegion.h" 14 | #include "nodePath.h" 15 | #include "pStatTimer.h" 16 | #include "luse.h" 17 | #include "graphicsOutput.h" 18 | #include "luiRoot.h" 19 | #include "luiObject.h" 20 | #include "cullableObject.h" 21 | #include "cullTraverser.h" 22 | #include "cullHandler.h" 23 | #include "orthographicLens.h" 24 | #include "cullBinAttrib.h" 25 | #include "depthTestAttrib.h" 26 | #include "depthWriteAttrib.h" 27 | #include "luiInputHandler.h" 28 | 29 | class EXPCL_LUI LUIRegion : public DisplayRegion { 30 | 31 | protected: 32 | LUIRegion(GraphicsOutput* window, const LVecBase4& dimensions, 33 | const string& context_name); 34 | 35 | virtual void do_cull(CullHandler* cull_handler, SceneSetup* scene_setup, 36 | GraphicsStateGuardian* gsg, Thread* current_thread); 37 | 38 | PUBLISHED: 39 | virtual ~LUIRegion(); 40 | 41 | INLINE static LUIRegion* make(const string& context_name, 42 | GraphicsOutput* window); 43 | INLINE static LUIRegion* make(const string& context_name, 44 | GraphicsOutput* window, 45 | const LVecBase4& dimensions); 46 | INLINE LUIObject* get_root() const; 47 | 48 | MAKE_PROPERTY(root, get_root); 49 | 50 | INLINE void set_input_handler(LUIInputHandler* handler); 51 | INLINE LUIInputHandler* get_input_handler() const; 52 | 53 | INLINE void set_render_wireframe(bool wireframe); 54 | INLINE void toggle_render_wireframe(); 55 | 56 | private: 57 | 58 | PT(OrthographicLens) _lens; 59 | PT(LUIRoot) _lui_root; 60 | PT(LUIInputHandler) _input_handler; 61 | int _width, _height; 62 | bool _wireframe; 63 | 64 | PT(Shader) _object_shader; 65 | PT(Texture) _empty_tex; 66 | 67 | public: 68 | static TypeHandle get_class_type() { 69 | return _type_handle; 70 | } 71 | static void init_type() { 72 | DisplayRegion::init_type(); 73 | register_type(_type_handle, "LUIRegion", 74 | DisplayRegion::get_class_type()); 75 | } 76 | virtual TypeHandle get_type() const { 77 | return get_class_type(); 78 | } 79 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 80 | 81 | private: 82 | static TypeHandle _type_handle; 83 | 84 | }; 85 | 86 | #include "luiRegion.I" 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /source/luiText.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE void LUIText::set_font(const string& font_name) { 3 | _font = LUIFontPool::get_global_ptr()->get_font(font_name); 4 | update_text(); 5 | } 6 | 7 | INLINE void LUIText::set_text(const wstring& text) { 8 | if (_text != text) { 9 | _text = text; 10 | update_text(); 11 | } 12 | } 13 | 14 | INLINE void LUIText::set_font_size(float size) { 15 | if (size != _font_size) { 16 | _font_size = size; 17 | update_text(); 18 | } 19 | } 20 | 21 | INLINE DynamicTextFont* LUIText::get_font() const{ 22 | return _font; 23 | } 24 | 25 | INLINE const wstring& LUIText::get_text() const { 26 | return _text; 27 | } 28 | 29 | INLINE float LUIText::get_font_size() const { 30 | return _font_size; 31 | } 32 | 33 | INLINE void LUIText::set_wordwrap(bool wrap) { 34 | _wordwrap = wrap; 35 | update_text(); 36 | } 37 | 38 | INLINE bool LUIText::get_wordwrap() const { 39 | return _wordwrap; 40 | } 41 | -------------------------------------------------------------------------------- /source/luiText.h: -------------------------------------------------------------------------------- 1 | // Filename: luiText.h 2 | // Created by: tobspr (14Sep14) 3 | // 4 | 5 | #ifndef LUI_TEXT_H 6 | #define LUI_TEXT_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | #include "referenceCount.h" 12 | #include "config_lui.h" 13 | #include "luiObject.h" 14 | #include "luiIterators.h" 15 | #include "luiFontPool.h" 16 | #include "luiColorable.h" 17 | #include "luiSprite.h" 18 | #include "dynamicTextFont.h" 19 | #include "dynamicTextGlyph.h" 20 | #include "textFont.h" 21 | #include "texture.h" 22 | #include "dcast.h" 23 | 24 | class EXPCL_LUI LUIText : public LUIObject { 25 | 26 | PUBLISHED: 27 | 28 | LUIText(PyObject* self, 29 | LUIObject* parent, const wstring& text, const string& font_name="default", 30 | float font_size=16.0f, float x=0.0f, float y=0.0f, bool wordwrap=false); 31 | ~LUIText(); 32 | 33 | INLINE void set_font(const string& font_name); 34 | INLINE DynamicTextFont* get_font() const; 35 | 36 | INLINE void set_text(const wstring& text); 37 | INLINE const wstring& get_text() const; 38 | 39 | INLINE void set_font_size(float size); 40 | INLINE float get_font_size() const; 41 | 42 | INLINE void set_wordwrap(bool wrap); 43 | INLINE bool get_wordwrap() const; 44 | 45 | int get_char_index(float pos) const; 46 | float get_char_pos(int char_index) const; 47 | 48 | virtual void ls(int indent = 0); 49 | 50 | MAKE_PROPERTY(font, get_font, set_font); 51 | MAKE_PROPERTY(text, get_text, set_text); 52 | MAKE_PROPERTY(font_size, get_font_size, set_font_size); 53 | 54 | protected: 55 | 56 | void update_text(); 57 | vector get_line_breaks(); 58 | 59 | DynamicTextFont* _font; 60 | wstring _text; 61 | float _font_size; 62 | bool _wordwrap; 63 | pvector _glyphs; 64 | 65 | 66 | public: 67 | static TypeHandle get_class_type() { 68 | return _type_handle; 69 | } 70 | static void init_type() { 71 | LUIObject::init_type(); 72 | register_type(_type_handle, "LUIText", LUIObject::get_class_type()); 73 | } 74 | virtual TypeHandle get_type() const { 75 | return get_class_type(); 76 | } 77 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 78 | 79 | private: 80 | static TypeHandle _type_handle; 81 | 82 | 83 | }; 84 | 85 | #include "luiText.I" 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /source/luiVertexChunk.I: -------------------------------------------------------------------------------- 1 | 2 | INLINE bool LUIVertexChunk::is_empty() const { 3 | return _sprite_count == 0; 4 | } 5 | 6 | INLINE bool LUIVertexChunk::has_space() const { 7 | return _sprite_count < _chunk_size; 8 | } 9 | 10 | INLINE Geom* LUIVertexChunk::get_geom() const { 11 | return _geom; 12 | } 13 | 14 | INLINE int LUIVertexChunk::reserve_slot(LUISprite* sprite) { 15 | nassertr(has_space(), 0); 16 | 17 | if (lui_cat.is_spam()) { 18 | lui_cat.spam() << "Reserving slot .. " << endl; 19 | } 20 | 21 | int slot = -1; 22 | for (int i = 0; i < _chunk_size; i++) { 23 | if (_children[i] == nullptr) { 24 | // found slot 25 | slot = i; 26 | break; 27 | } 28 | } 29 | 30 | // As we checked for has_space above, this should never happen 31 | nassertr(slot >= 0 && slot < _chunk_size, 0); 32 | 33 | _children[slot] = sprite; 34 | _sprite_count ++; 35 | 36 | return slot; 37 | } 38 | 39 | INLINE void LUIVertexChunk::free_slot(int slot) { 40 | 41 | nassertv(slot < _chunk_size); 42 | nassertv(!is_empty()); 43 | 44 | if (_children[slot] == nullptr) { 45 | lui_cat.error() << "Cannot free slot, as it is not used" << endl; 46 | return; 47 | } 48 | 49 | _children[slot] = nullptr; 50 | _sprite_count --; 51 | 52 | 53 | if (lui_cat.is_spam()) { 54 | lui_cat.spam() << "Free slot " << slot << endl; 55 | } 56 | 57 | for (int i = 0; i < 4; i++) { 58 | memset(get_slot_ptr(slot), 0, sizeof(LUIVertexData) * 4); 59 | } 60 | 61 | 62 | if (_sprite_count < 1) { 63 | if (lui_cat.is_spam()) { 64 | // TODO: Unregister from vertex pool 65 | lui_cat.debug() << "Detected empty vertex chunk, should be garbarge collected" << endl; 66 | } 67 | } 68 | } 69 | 70 | INLINE void* LUIVertexChunk::get_slot_ptr(int slot) const { 71 | 72 | // Make sure the write pointer is correct 73 | nassertr(_vertex_data->modify_array(0)->modify_handle()->get_write_pointer() == _write_pointer, nullptr); 74 | 75 | // Make sure we don't write at the wrong location 76 | nassertr(slot < _chunk_size, nullptr); 77 | 78 | return (void*)((uintptr_t)_write_pointer + sizeof(LUIVertexData) * 4 * slot); 79 | } 80 | -------------------------------------------------------------------------------- /source/luiVertexChunk.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiVertexChunk.h" 3 | 4 | 5 | LUIVertexChunk::LUIVertexChunk(int chunk_size) 6 | : _chunk_size(chunk_size), _sprite_count(0) { 7 | 8 | if (lui_cat.is_spam()) { 9 | lui_cat.spam() << "Constructed new chunk of size " << chunk_size << endl; 10 | } 11 | 12 | CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3c4t2(); 13 | _vertex_data = new GeomVertexData("VertexPool", format, Geom::UH_dynamic); 14 | _vertex_data->set_num_rows(chunk_size * 4); 15 | 16 | GeomVertexWriter write_vertex(_vertex_data, "vertex"); 17 | GeomVertexWriter write_texcoord(_vertex_data, "texcoord"); 18 | GeomVertexWriter write_color(_vertex_data, "color"); 19 | 20 | for (int i = 0; i < chunk_size*4; i++) { 21 | write_vertex.add_data3f(0, 0, 0); 22 | write_color.add_data4f(1,1,1,1); 23 | write_texcoord.add_data2f(0, 0); 24 | } 25 | 26 | _triangles = new GeomTriangles(Geom::UH_dynamic); 27 | _triangles->reserve_num_vertices(chunk_size * 2); 28 | 29 | // Initialize triangles, each sprite emits 4, we use indexing to create 2 tris from that 30 | for (int i = 0; i < chunk_size; i++) { 31 | int vtx_index = i * 4; 32 | // _triangles->add_vertices(vtx_index + 0, vtx_index + 1, vtx_index + 2); 33 | // _triangles->add_vertices(vtx_index + 0, vtx_index + 2, vtx_index + 3); 34 | 35 | _triangles->add_vertices(vtx_index + 2, vtx_index + 1, vtx_index + 0); 36 | _triangles->add_vertices(vtx_index + 3, vtx_index + 2, vtx_index + 0); 37 | } 38 | 39 | _geom = new Geom(_vertex_data); 40 | _geom->add_primitive(_triangles); 41 | 42 | _write_pointer = _vertex_data->modify_array(0)->modify_handle()->get_write_pointer(); 43 | 44 | // Initialize child array 45 | _children = new LUISprite*[chunk_size]; 46 | 47 | for (int i = 0; i < chunk_size; i++) { 48 | _children[i] = nullptr; 49 | } 50 | 51 | } 52 | 53 | LUIVertexChunk::~LUIVertexChunk() { 54 | // TODO: I probably missed something here 55 | if (lui_cat.is_spam()) { 56 | lui_cat.spam() << "Destructed vertex chunk" << endl; 57 | } 58 | delete [] _children; 59 | } 60 | -------------------------------------------------------------------------------- /source/luiVertexChunk.h: -------------------------------------------------------------------------------- 1 | // Filename: luiVertexChunk.h 2 | // Created by: tobspr (02Sep14) 3 | // 4 | 5 | #ifndef LUI_VERTEX_CHUNK_H 6 | #define LUI_VERTEX_CHUNK_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | #include "texture.h" 12 | #include "luiSprite.h" 13 | #include "luiVertexData.h" 14 | #include "luiSprite.h" 15 | #include "geomVertexFormat.h" 16 | #include "geomVertexData.h" 17 | #include "geomVertexWriter.h" 18 | #include "geomTriangles.h" 19 | #include "geom.h" 20 | 21 | class LUISprite; 22 | 23 | class LUIVertexChunk { 24 | 25 | public: 26 | 27 | LUIVertexChunk(int chunk_size); 28 | ~LUIVertexChunk(); 29 | 30 | INLINE bool is_empty() const; 31 | INLINE bool has_space() const; 32 | INLINE Geom* get_geom() const; 33 | 34 | INLINE int reserve_slot(LUISprite* sprite); 35 | INLINE void free_slot(int slot); 36 | INLINE void* get_slot_ptr(int slot) const; 37 | 38 | private: 39 | 40 | PT(GeomVertexData) _vertex_data; 41 | PT(GeomTriangles) _triangles; 42 | PT(Geom) _geom; 43 | 44 | int _sprite_count; 45 | int _chunk_size; 46 | void* _write_pointer; 47 | LUISprite** _children; 48 | 49 | }; 50 | 51 | #include "luiVertexChunk.I" 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /source/luiVertexData.h: -------------------------------------------------------------------------------- 1 | // Filename: luiVertexData.h 2 | // Created by: tobspr (01Sep14) 3 | // 4 | 5 | #ifndef LUI_VERTEX_DATA_H 6 | #define LUI_VERTEX_DATA_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | 12 | #include 13 | 14 | struct LUIVertexData { 15 | float x, y, z; 16 | unsigned char color[4]; 17 | float u, v; 18 | uint16_t texindex; 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /source/luiVertexPool.I: -------------------------------------------------------------------------------- 1 | 2 | 3 | INLINE int LUIVertexPool::get_num_chunks() const { 4 | return _chunks.size(); 5 | 6 | } 7 | INLINE LUIVertexChunk* LUIVertexPool::get_chunk(int n) const { 8 | nassertr(n >= 0 && n < _chunks.size(), nullptr); 9 | return _chunks[n]; 10 | } 11 | -------------------------------------------------------------------------------- /source/luiVertexPool.cxx: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "luiVertexPool.h" 4 | 5 | LUIVertexPool::LUIVertexPool(Texture* tex) : 6 | _tex(tex) 7 | { 8 | if (lui_cat.is_spam()) { 9 | lui_cat.spam() << "Constructed new LUIVertex pool" << endl; 10 | } 11 | 12 | } 13 | 14 | LUIVertexPool::~LUIVertexPool() { 15 | if (lui_cat.is_spam()) { 16 | lui_cat.spam() << "Destructing LUIVertex pool" << endl; 17 | } 18 | 19 | for (int i = 0; i < _chunks.size(); i++) { 20 | delete _chunks[i]; 21 | } 22 | _chunks.clear(); 23 | 24 | } 25 | 26 | LUIChunkDescriptor* LUIVertexPool::allocate_slot(LUISprite* child) { 27 | 28 | LUIVertexChunk* chunk = nullptr; 29 | 30 | for (int i = 0; i < _chunks.size(); i++) { 31 | LUIVertexChunk* current = _chunks[i]; 32 | if (current->has_space()) { 33 | chunk = current; 34 | break; 35 | } 36 | } 37 | 38 | if (chunk == nullptr) { 39 | if (lui_cat.is_spam()) { 40 | lui_cat.spam() << "Allocating new lui vertex chunk .." << endl; 41 | } 42 | allocate_chunk(); 43 | chunk = _chunks.back(); 44 | } else { 45 | if (lui_cat.is_spam()) { 46 | lui_cat.spam() << "Found chunk at " << chunk << endl; 47 | } 48 | } 49 | 50 | // At this place, the chunk should not be nullptr. Either we allocated a new one, 51 | // or we took an existing one, but in all cases we have one. 52 | nassertr(chunk != nullptr, nullptr); 53 | 54 | int slot = chunk->reserve_slot(child); 55 | nassertr(slot >= 0, nullptr); 56 | 57 | LUIChunkDescriptor* result = new LUIChunkDescriptor(); 58 | result->set_chunk(chunk); 59 | result->set_slot(slot); 60 | return result; 61 | } 62 | 63 | void LUIVertexPool::allocate_chunk() { 64 | LUIVertexChunk* chunk = new LUIVertexChunk(10000); 65 | _chunks.push_back(chunk); 66 | } 67 | -------------------------------------------------------------------------------- /source/luiVertexPool.h: -------------------------------------------------------------------------------- 1 | // Filename: luiVertexPool.h 2 | // Created by: tobspr (28Aug14) 3 | // 4 | 5 | #ifndef LUI_VERTEX_POOL_H 6 | #define LUI_VERTEX_POOL_H 7 | 8 | #include "pandabase.h" 9 | #include "pandasymbols.h" 10 | #include "luse.h" 11 | #include "texture.h" 12 | #include "luiSprite.h" 13 | #include "luiVertexData.h" 14 | #include "luiVertexChunk.h" 15 | #include "luiChunkDescriptor.h" 16 | 17 | #include "geomVertexFormat.h" 18 | #include "geomVertexData.h" 19 | #include "geomVertexWriter.h" 20 | #include "geomTriangles.h" 21 | #include "bitArray.h" 22 | #include "geom.h" 23 | 24 | class LUISprite; 25 | class LUIVertexChunk; 26 | 27 | class LUIVertexPool { 28 | 29 | public: 30 | 31 | LUIVertexPool(Texture* tex); 32 | ~LUIVertexPool(); 33 | 34 | LUIChunkDescriptor* allocate_slot(LUISprite* child); 35 | 36 | INLINE int get_num_chunks() const; 37 | INLINE LUIVertexChunk* get_chunk(int n) const; 38 | 39 | private: 40 | 41 | void allocate_chunk(); 42 | 43 | PT(Texture) _tex; 44 | vector _chunks; 45 | 46 | }; 47 | 48 | #include "luiVertexPool.I" 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /source/luiVerticalLayout.cxx: -------------------------------------------------------------------------------- 1 | 2 | #include "luiVerticalLayout.h" 3 | 4 | TypeHandle LUIVerticalLayout::_type_handle; 5 | NotifyCategoryDef(luiVerticalLayout, ":lui"); 6 | 7 | 8 | LUIVerticalLayout::LUIVerticalLayout(PyObject* self, LUIObject* parent, float spacing) 9 | : LUIBaseLayout(self) { 10 | set_spacing(spacing); 11 | set_parent(parent); 12 | } 13 | 14 | void LUIVerticalLayout::init_container(LUIObject* container) { 15 | } 16 | 17 | float LUIVerticalLayout::get_metric(LUIBaseElement* element) { 18 | return element->get_height(); 19 | } 20 | 21 | void LUIVerticalLayout::set_metric(LUIBaseElement* element, float metric) { 22 | element->set_height(metric); 23 | } 24 | 25 | void LUIVerticalLayout::set_offset(LUIBaseElement* element, float offset) { 26 | element->set_top(offset); 27 | } 28 | 29 | bool LUIVerticalLayout::has_space(LUIBaseElement* element) { 30 | return element->has_width(); 31 | } 32 | 33 | void LUIVerticalLayout::set_full_metric(LUIBaseElement* element) { 34 | element->set_width("100%"); 35 | } 36 | 37 | void LUIVerticalLayout::clear_metric(LUIBaseElement* element) { 38 | element->clear_width(); 39 | } 40 | -------------------------------------------------------------------------------- /source/luiVerticalLayout.h: -------------------------------------------------------------------------------- 1 | // Filename: luiVerticalLayout.h 2 | // Created by: tobspr (31Jan16) 3 | // 4 | 5 | #ifndef LUI_VERTICAL_LAYOUT_H 6 | #define LUI_VERTICAL_LAYOUT_H 7 | 8 | #include "config_lui.h" 9 | #include "luiBaseLayout.h" 10 | 11 | #include "pandabase.h" 12 | NotifyCategoryDecl(luiVerticalLayout, EXPCL_LUI, EXPTP_LUI); 13 | 14 | class EXPCL_LUI LUIVerticalLayout : public LUIBaseLayout { 15 | 16 | PUBLISHED: 17 | LUIVerticalLayout(PyObject* self, LUIObject* parent, float spacing = 0.0); 18 | 19 | protected: 20 | // Interfaces 21 | void init_container(LUIObject* container); 22 | float get_metric(LUIBaseElement* element); 23 | void set_metric(LUIBaseElement* element, float metric); 24 | void set_offset(LUIBaseElement* element, float offset); 25 | bool has_space(LUIBaseElement* element); 26 | void set_full_metric(LUIBaseElement* element); 27 | void clear_metric(LUIBaseElement* element); 28 | 29 | public: 30 | static TypeHandle get_class_type() { 31 | return _type_handle; 32 | } 33 | static void init_type() { 34 | LUIBaseLayout::init_type(); 35 | register_type(_type_handle, "LUIVerticalLayout", LUIBaseLayout::get_class_type()); 36 | } 37 | virtual TypeHandle get_type() const { 38 | return get_class_type(); 39 | } 40 | virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 41 | 42 | private: 43 | static TypeHandle _type_handle; 44 | 45 | }; 46 | 47 | #endif // LUI_VERTICAL_LAYOUT_H 48 | --------------------------------------------------------------------------------