Skip to content

Commit

Permalink
Merge branch 'development' of https://github.com/pvcraven/arcade into…
Browse files Browse the repository at this point in the history
… development
  • Loading branch information
einarf committed Jun 20, 2020
2 parents b77020a + e5b8153 commit 717cc30
Show file tree
Hide file tree
Showing 13 changed files with 229 additions and 17 deletions.
5 changes: 2 additions & 3 deletions arcade/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
The main window class that all object-oriented applications should
derive from.
"""
import logging
import time
from numbers import Number
from typing import Tuple, List, Optional, TYPE_CHECKING
from typing import Tuple, Optional

import pyglet
import pyglet.gl as gl
Expand All @@ -16,8 +17,6 @@
from arcade import set_window
from arcade.context import ArcadeContext

import logging

LOG = logging.getLogger(__name__)

MOUSE_BUTTON_LEFT = 1
Expand Down
38 changes: 33 additions & 5 deletions arcade/examples/gui_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,36 @@
from arcade.gui import UIManager


class MyFlatButton(arcade.gui.UIFlatButton):
"""
To capture a button click, subclass the button and override on_click.
"""
def on_click(self):
""" Called when user lets off button """
print("Click flat button. ")

class MyGhostFlatButton(arcade.gui.UIGhostFlatButton):
"""
For this subclass, we create a custom init, that takes in another
parameter, the UI text box. We use that parameter and print the contents
of the text entry box when the ghost button is clicked.
"""

def __init__(self, center_x, center_y, input_box):
super().__init__(
'GhostFlatButton',
center_x=center_x,
center_y=center_y,
width=250,
# height=20
)
self.input_box = input_box

def on_click(self):
""" Called when user lets off button """
print(f"Click ghost flat button. {self.input_box.text}")


class MyView(arcade.View):
"""
Main view. Really the only view in this example. """
Expand Down Expand Up @@ -66,7 +96,7 @@ def setup(self):
self.ui_manager.add_ui_element(button)

# right side elements
button = arcade.gui.UIFlatButton(
button = MyFlatButton(
'FlatButton',
center_x=right_column_x,
center_y=y_slot * 1,
Expand All @@ -75,12 +105,10 @@ def setup(self):
)
self.ui_manager.add_ui_element(button)

button = arcade.gui.UIGhostFlatButton(
'GhostFlatButton',
button = MyGhostFlatButton(
center_x=right_column_x,
center_y=y_slot * 2,
width=250,
# height=20
input_box=ui_input_box
)
self.ui_manager.add_ui_element(button)

Expand Down
5 changes: 3 additions & 2 deletions arcade/experimental/shadertoy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, source: str):

self.ctx = self.window.ctx
self.source: str = source
self.mouse_pos: Tuple[float, float] = 0, 0
self.mouse_pos = 0, 0
self.quad = geometry.quad_2d_fs()

self.program = self.ctx.program(
Expand Down Expand Up @@ -66,7 +66,8 @@ def draw(self, time: float = 0, target=None):
except KeyError:
pass
try:
self.program['iResolution'] = self.window.get_framebuffer_size()
if self.window is not None:
self.program['iResolution'] = self.window.get_framebuffer_size()
except KeyError:
pass

Expand Down
7 changes: 5 additions & 2 deletions arcade/gui/elements/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from typing import Optional

from pyglet.event import EventDispatcher

from arcade import Texture

from arcade.gui import UIElement, UIEvent, MOUSE_PRESS, MOUSE_RELEASE
from arcade.gui.ui_style import UIStyle


class UIClickable(UIElement):
class UIClickable(EventDispatcher, UIElement):
""" Texture based UIElement supporting hover and press, this should fit every use case"""

CLICKED = 'UIClickable_CLICKED'
Expand All @@ -22,6 +24,7 @@ def __init__(self,
id=id,
style=style
)
self.register_event_type('on_click')

self._pressed = False
self._hovered = False
Expand Down Expand Up @@ -103,7 +106,7 @@ def on_ui_event(self, event: UIEvent):
self.on_release()

if self.collides_with_point((event.get('x'), event.get('y'))):
self.on_click()
self.dispatch_event('on_click')

if self.mng:
self.mng.disptach_ui_event(UIEvent(UIClickable.CLICKED, ui_element=self))
Expand Down
3 changes: 3 additions & 0 deletions arcade/gui/elements/inputbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def __init__(self,
style=style,
**kwargs
)
self.register_event_type('on_enter')
self.style_classes.append('inputbox')

self.width = width if width is not None else 200
Expand Down Expand Up @@ -254,10 +255,12 @@ def on_ui_event(self, event: UIEvent):

if self.focused:
if event.type == TEXT_INPUT and event.get('text') == '\r':
self.dispatch_event('on_enter')
if self.mng:
self.mng.disptach_ui_event(UIEvent(UIInputBox.ENTER, ui_element=self))
return

self.text_adapter.on_event(event)

self.render_textures()

70 changes: 70 additions & 0 deletions arcade/gui/examples/show_decorator_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from typing import cast

import arcade
from arcade.gui import UILabel, UIInputBox, UIFlatButton, UIManager


class MyView(arcade.View):
def __init__(self, window: arcade.Window):
super().__init__()

self.window = window
self.ui_manager = UIManager(window)

def on_draw(self):
arcade.start_render()
arcade.set_background_color(arcade.color.BLACK)

def on_show(self):
print('on_show')
self.setup()

def setup(self):
self.ui_manager.purge_ui_elements()

self.ui_manager.add_ui_element(UILabel(
text='Username:',
center_x=100,
center_y=self.window.height // 2,
width=300,
height=40,
))

input_box = UIInputBox(center_x=350,
center_y=self.window.height // 2,
width=300,
height=40,
id='username')
self.ui_manager.add_ui_element(input_box)

submit_button = UIFlatButton(text='Login',
center_x=650,
center_y=self.window.height // 2,
width=200,
height=40,
id='submit_button')
self.ui_manager.add_ui_element(submit_button)

self.ui_manager.add_ui_element(UILabel(
text='',
center_x=self.window.width // 2,
center_y=self.window.height // 2 - 100,
width=600,
height=40,
id='login_message'
))

@input_box.event('on_enter')
@submit_button.event('on_click')
def submit():
username_input = cast(UIInputBox, self.ui_manager.find_by_id('username'))
username = username_input.text

login_message: UILabel = cast(UILabel, self.ui_manager.find_by_id('login_message'))
login_message.text = f'Welcome {username}, you are my first player.'


if __name__ == '__main__':
window = arcade.Window(title='ARCADE_GUI')
window.show_view(MyView(window))
arcade.run()
7 changes: 4 additions & 3 deletions arcade/gui/examples/show_id_example.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import cast

import arcade

from arcade.gui import UILabel, UIClickable, UIInputBox, UIEvent, UIFlatButton, UIManager
Expand Down Expand Up @@ -62,12 +64,11 @@ def on_ui_event(self, event: UIEvent):
# Trigger action if ENTER pressed in 'username'-UIInputBox
self.submit()

# noinspection PyTypeChecker
def submit(self):
username_input: UIInputBox = self.ui_manager.find_by_id('username')
username_input = cast(UIInputBox, self.ui_manager.find_by_id('username'))
username = username_input.text

login_message: UILabel = self.ui_manager.find_by_id('login_message')
login_message: UILabel = cast(UILabel, self.ui_manager.find_by_id('login_message'))
login_message.text = f'Welcome {username}, you are my first player.'


Expand Down
41 changes: 41 additions & 0 deletions arcade/gui/examples/show_image_from_style.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import arcade

import arcade.gui
from arcade.gui import UIManager


class MyView(arcade.View):
def __init__(self, window: arcade.Window):
super().__init__()

self.window = window
self.ui_manager = UIManager(window)

def on_draw(self):
arcade.start_render()

def on_show(self):
print('on_show')
self.setup()
arcade.set_background_color(arcade.color.BLACK)

def setup(self):
self.ui_manager.purge_ui_elements()

button_normal = arcade.load_texture(':resources:gui_basic_assets/red_button_normal.png')
hovered_texture = arcade.load_texture(':resources:gui_basic_assets/red_button_hover.png')
pressed_texture = arcade.load_texture(':resources:gui_basic_assets/red_button_press.png')
self.ui_manager.add_ui_element(arcade.gui.UIImageButton(
center_x=self.window.width // 2,
center_y=window.height // 2,
normal_texture=button_normal,
hover_texture=hovered_texture,
press_texture=pressed_texture,
text='UIImageButton',
))


if __name__ == '__main__':
window = arcade.Window(title='ARCADE_GUI')
window.show_view(MyView(window))
arcade.run()
22 changes: 22 additions & 0 deletions tests/test_gui/test_ui_clickable_interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ def test_uibutton_clicked(mock_mng, mock_button):
assert mock_button.on_click_called


def test_uibutton_click_dispatch_event(mock_mng, mock_button):
# GIVEN
mock_mng.add_ui_element(mock_button)
clicked = False

@mock_button.event('on_click')
def callback(*args):
nonlocal clicked
clicked = True

# WHEN
mock_mng.click(50, 50)

# THEN
assert clicked


def test_uibutton_has_on_click_event_type(mock_button):
# THEN
assert 'on_click' in mock_button.event_types


def test_uibutton_not_clicked_if_released_beside(mock_mng, mock_button):
mock_mng.add_ui_element(mock_button)

Expand Down
File renamed without changes.
48 changes: 46 additions & 2 deletions tests/test_gui/test_ui_inputbox.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import pytest
from arcade.key import *

from arcade.gui import UIEvent, TEXT_INPUT, TEXT_MOTION
from arcade.gui.elements.inputbox import UIInputBox
from . import T
from arcade.key import *
from tests.test_gui import T


@pytest.mark.skip('This is hard to test, we would have to check the rendered texture, or mock the render calls')
Expand Down Expand Up @@ -69,6 +69,50 @@ def test_emits_event_on_enter(mock_mng):
assert mock_mng.last_event.get('ui_element') == inputbox


def test_invokes_callback_on_return(mock_mng):
inputbox = UIInputBox(center_x=30, center_y=30, width=40, height=40)
inputbox.text = 'Best Game Lib!'
inputbox.cursor_index = 5
inputbox.on_focus()
mock_mng.add_ui_element(inputbox)

invoked = False

def callback():
nonlocal invoked
invoked = True

inputbox.on_enter = callback

inputbox.on_ui_event(UIEvent(TEXT_INPUT, text='\r'))

assert invoked is True


def test_invokes_decorator_on_return(mock_mng):
inputbox = UIInputBox(center_x=30, center_y=30, width=40, height=40)
inputbox.text = 'Best Game Lib!'
inputbox.cursor_index = 5
inputbox.on_focus()
mock_mng.add_ui_element(inputbox)

invoked = False

@inputbox.event('on_enter')
def callback():
nonlocal invoked
invoked = True

inputbox.on_ui_event(UIEvent(TEXT_INPUT, text='\r'))

assert invoked is True


def test_ui_inputbox_has_on_enter_event_type():
inputbox = UIInputBox(center_x=30, center_y=30, width=40, height=40)
assert 'on_enter' in inputbox.event_types


def test_changes_text_on_backspace(draw_commands, mock_mng):
inputbox = UIInputBox(center_x=30, center_y=30, width=40, height=40)
inputbox.text = 'Best Game Lib!'
Expand Down
File renamed without changes.

0 comments on commit 717cc30

Please sign in to comment.