- added spinner controls to audio panel for editing sound effects
- added play and stop buttons to audio panel - box generating function can generate box without text
This commit is contained in:
parent
987b154b26
commit
513e8fad4e
363
pgfw/Audio.py
363
pgfw/Audio.py
|
@ -1,3 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os, re, shutil, pygame
|
||||
|
||||
from .GameChild import *
|
||||
|
@ -54,9 +56,20 @@ class Audio(GameChild):
|
|||
#
|
||||
def load_sfx(self, sfx_location=None):
|
||||
for name, sfx_definition in self.get_configuration("sfx").items():
|
||||
path, volume = sfx_definition.split(",")
|
||||
volume = float(volume)
|
||||
self.load_sfx_file(path, name, True, volume=volume)
|
||||
sfx_definition_members = sfx_definition.split(",")
|
||||
path, volume, fade_out, loops, maxtime = sfx_definition_members[0], 1.0, 0, 0, 0
|
||||
for ii, member in enumerate(sfx_definition_members[1:]):
|
||||
if ii == 0:
|
||||
volume = float(member)
|
||||
elif ii == 1:
|
||||
fade_out = float(member)
|
||||
elif ii == 2:
|
||||
loops = int(member)
|
||||
elif ii == 3:
|
||||
maxtime = float(member)
|
||||
self.load_sfx_file(
|
||||
path, name, True, volume=volume, fade_out=fade_out, loops=loops,
|
||||
maxtime=maxtime)
|
||||
if sfx_location is None:
|
||||
sfx_location = self.get_configuration("audio", "sfx-project-path") + \
|
||||
self.get_configuration("audio", "sfx-default-path")
|
||||
|
@ -78,16 +91,18 @@ class Audio(GameChild):
|
|||
prefix = re.sub("/", "_", prefix) + "_"
|
||||
self.load_sfx_file(os.path.join(node, leaf,), prefix=prefix)
|
||||
|
||||
def load_sfx_file(self, path, name=None, replace=False, prefix="", volume=1.0):
|
||||
def load_sfx_file(self, path, name=None, replace=False, prefix="",
|
||||
volume=1.0, fade_out=0, loops=0, maxtime=0):
|
||||
path = self.get_resource(path)
|
||||
if path and path.split(".")[-1] in self.get_configuration("audio", "sfx-extensions"):
|
||||
if name is None:
|
||||
name = prefix + re.sub("\.[^.]*$", "", os.path.basename(path))
|
||||
if not replace and name in self.sfx:
|
||||
print("skipping existing sound effect for %s: %s" % (name, path))
|
||||
print("skipping existing sound effect for {}: {}".format(name, path))
|
||||
else:
|
||||
print("loading sound effect %s into %s" % (path, name))
|
||||
self.sfx[name] = SoundEffect(self, path, volume)
|
||||
print("loading sound effect {} into {}".format(path, name))
|
||||
self.sfx[name] = SoundEffect(
|
||||
self, path, volume, loops, fade_out, maxtime=maxtime)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -104,21 +119,35 @@ class Audio(GameChild):
|
|||
|
||||
class SoundEffect(GameChild, pygame.mixer.Sound):
|
||||
|
||||
def __init__(self, parent, path, volume=1.0):
|
||||
def __init__(self, parent, path, volume=1.0, loops=0, fade_out_length=0,
|
||||
fade_in_length=0, maxtime=0):
|
||||
self.path = path
|
||||
GameChild.__init__(self, parent)
|
||||
pygame.mixer.Sound.__init__(self, path)
|
||||
self.display_surface = self.get_display_surface()
|
||||
self.initial_volume = volume
|
||||
self.set_volume(self.initial_volume * self.get_configuration("audio", "sfx-volume"))
|
||||
self.local_volume = volume
|
||||
self.loops = loops
|
||||
self.fade_out_length = fade_out_length
|
||||
self.fade_in_length = fade_in_length
|
||||
self.maxtime = maxtime
|
||||
|
||||
def play(self, loops=0, maxtime=0, fade_ms=0, position=None, x=None):
|
||||
self.set_volume(self.initial_volume * self.get_configuration("audio", "sfx-volume"))
|
||||
def play(self, loops=None, maxtime=None, fade_ms=None, position=None,
|
||||
x=None):
|
||||
self.set_volume(
|
||||
self.local_volume * self.get_configuration("audio", "sfx-volume"))
|
||||
if loops is None:
|
||||
loops = self.loops
|
||||
if maxtime is None:
|
||||
maxtime = int(self.maxtime * 1000)
|
||||
if fade_ms is None:
|
||||
fade_ms = int(self.fade_in_length * 1000)
|
||||
channel = pygame.mixer.Sound.play(self, loops, maxtime, fade_ms)
|
||||
if x is not None:
|
||||
position = float(x) / self.display_surface.get_width()
|
||||
if position is not None and channel is not None:
|
||||
channel.set_volume(*self.get_panning(position))
|
||||
if self.fade_out_length > 0:
|
||||
self.fadeout(int(self.fade_out_length * 1000))
|
||||
return channel
|
||||
|
||||
def get_panning(self, position):
|
||||
|
@ -126,12 +155,45 @@ class SoundEffect(GameChild, pygame.mixer.Sound):
|
|||
1 + min(0, ((position - .5) * 2))
|
||||
|
||||
def adjust_volume(self, increment):
|
||||
self.initial_volume += increment
|
||||
if self.initial_volume > 1.0:
|
||||
self.initial_volume = 1.0
|
||||
elif self.initial_volume < 0:
|
||||
self.initial_volume = 0
|
||||
self.set_volume(self.initial_volume * self.get_configuration("audio", "sfx-volume"))
|
||||
self.local_volume += increment
|
||||
if self.local_volume > 1.0:
|
||||
self.local_volume = 1.0
|
||||
elif self.local_volume < 0:
|
||||
self.local_volume = 0
|
||||
return self.local_volume
|
||||
|
||||
def adjust_loop_count(self, increment):
|
||||
self.loops += increment
|
||||
if self.loops < -1:
|
||||
self.loops = -1
|
||||
return self.loops
|
||||
|
||||
def adjust_fade_in_length(self, increment):
|
||||
self.fade_in_length += increment
|
||||
limit = self.get_length() * (self.loops + 1)
|
||||
if self.fade_in_length < 0:
|
||||
self.fade_in_length = 0
|
||||
elif self.loops > -1 and self.fade_in_length > limit:
|
||||
self.fade_in_length = limit
|
||||
return self.fade_in_length
|
||||
|
||||
def adjust_fade_out_length(self, increment):
|
||||
self.fade_out_length += increment
|
||||
limit = self.get_length() * (self.loops + 1)
|
||||
if self.fade_out_length < 0:
|
||||
self.fade_out_length = 0
|
||||
elif self.loops > -1 and self.fade_out_length > limit:
|
||||
self.fade_out_length = limit
|
||||
return self.fade_out_length
|
||||
|
||||
def adjust_maxtime(self, increment):
|
||||
self.maxtime += increment
|
||||
limit = self.get_length() * (self.loops + 1)
|
||||
if self.maxtime < 0:
|
||||
self.maxtime = 0
|
||||
elif self.loops > -1 and self.maxtime > limit:
|
||||
self.maxtime = limit
|
||||
return self.maxtime
|
||||
|
||||
|
||||
class AudioPanel(Animation):
|
||||
|
@ -141,6 +203,10 @@ class AudioPanel(Animation):
|
|||
def __init__(self, parent):
|
||||
Animation.__init__(self, parent)
|
||||
self.rows = []
|
||||
font_path = self.get_resource(self.get_configuration("audio", "panel-font"))
|
||||
self.font_large = pygame.font.Font(font_path, 15)
|
||||
self.font_medium = pygame.font.Font(font_path, 12)
|
||||
self.font_small = pygame.font.Font(font_path, 8)
|
||||
self.file_browser = AudioPanelFileBrowser(self)
|
||||
self.subscribe(self.respond)
|
||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||
|
@ -158,7 +224,7 @@ class AudioPanel(Animation):
|
|||
def activate(self):
|
||||
pygame.mouse.set_visible(True)
|
||||
self.active = True
|
||||
self.build()
|
||||
# self.build()
|
||||
|
||||
def deactivate(self):
|
||||
pygame.mouse.set_visible(self.get_configuration("mouse", "visible"))
|
||||
|
@ -171,6 +237,8 @@ class AudioPanel(Animation):
|
|||
self.deactivate()
|
||||
else:
|
||||
self.activate()
|
||||
if not self.rows:
|
||||
self.build()
|
||||
elif self.active:
|
||||
if event.type == pygame.MOUSEBUTTONDOWN and self.file_browser.is_hidden():
|
||||
if event.button == 5:
|
||||
|
@ -180,7 +248,7 @@ class AudioPanel(Animation):
|
|||
|
||||
def build(self):
|
||||
for row in self.rows:
|
||||
row.unsubscribe(row.respond, pygame.MOUSEBUTTONDOWN)
|
||||
row.unsubscribe()
|
||||
del row
|
||||
self.rows = []
|
||||
for key in sorted(self.parent.sfx):
|
||||
|
@ -195,6 +263,7 @@ class AudioPanel(Animation):
|
|||
index = self.row_offset
|
||||
for row in self.rows:
|
||||
row.location.bottom = 0
|
||||
row.update()
|
||||
while corner.y < dsr.height - self.MARGIN:
|
||||
row = self.rows[index % len(self.rows)]
|
||||
row.location.topleft = corner.copy()
|
||||
|
@ -206,19 +275,53 @@ class AudioPanel(Animation):
|
|||
|
||||
class AudioPanelRow(BlinkingSprite):
|
||||
|
||||
BACKGROUND = pygame.Color(255, 255, 255, 180)
|
||||
FOREGROUND = pygame.Color(0, 0, 0, 180)
|
||||
WIDTH = .6
|
||||
FONT_SIZE = 18
|
||||
BACKGROUND = pygame.Color(255, 255, 255, 210)
|
||||
FOREGROUND = pygame.Color(0, 0, 0, 210)
|
||||
WIDTH = .5
|
||||
HEIGHT = 30
|
||||
INDENT = 4
|
||||
MAX_NAME_WIDTH = .7
|
||||
SLIDER_W = 60
|
||||
BUTTON_W = 30
|
||||
|
||||
def __init__(self, parent, key):
|
||||
BlinkingSprite.__init__(self, parent, 500)
|
||||
self.key = key
|
||||
self.selected = False
|
||||
self.font = self.parent.font_large
|
||||
self.build()
|
||||
font_medium = self.parent.font_medium
|
||||
font_small = self.parent.font_small
|
||||
self.volume_spinner = AudioPanelSpinner(
|
||||
self, font_medium, font_small, self.SLIDER_W, self.location.h, .05,
|
||||
self.get_sound_effect().local_volume,
|
||||
self.get_sound_effect().adjust_volume, self.FOREGROUND,
|
||||
self.BACKGROUND, 2, "vol")
|
||||
self.fade_out_spinner = AudioPanelSpinner(
|
||||
self, font_medium, font_small, self.SLIDER_W, self.location.h, .1,
|
||||
self.get_sound_effect().fade_out_length,
|
||||
self.get_sound_effect().adjust_fade_out_length, self.FOREGROUND,
|
||||
self.BACKGROUND, 1, "fade")
|
||||
self.loops_spinner = AudioPanelSpinner(
|
||||
self, font_medium, font_small, self.SLIDER_W, self.location.h, 1,
|
||||
self.get_sound_effect().loops,
|
||||
self.get_sound_effect().adjust_loop_count, self.FOREGROUND,
|
||||
self.BACKGROUND, 0, "loops")
|
||||
self.maxtime_spinner = AudioPanelSpinner(
|
||||
self, font_medium, font_small, self.SLIDER_W, self.location.h, .1,
|
||||
self.get_sound_effect().maxtime,
|
||||
self.get_sound_effect().adjust_maxtime, self.FOREGROUND,
|
||||
self.BACKGROUND, 1, "cutoff")
|
||||
self.play_button = AudioPanelButton(self, self.get_sound_effect().play)
|
||||
frame = pygame.Surface((self.BUTTON_W, self.location.h), SRCALPHA)
|
||||
frame.fill(self.BACKGROUND)
|
||||
stop_button_frame = frame.copy()
|
||||
w, h = frame.get_size()
|
||||
pygame.draw.polygon(frame, self.FOREGROUND, ((w * .25, h * .25), (w * .25, h * .75), (w * .75, h * .5)))
|
||||
self.play_button.add_frame(frame)
|
||||
self.stop_button = AudioPanelButton(self, self.get_sound_effect().stop)
|
||||
stop_button_frame.fill(self.FOREGROUND, (w * .25, h * .25, w * .5, h * .5))
|
||||
self.stop_button.add_frame(stop_button_frame)
|
||||
self.stop_blinking()
|
||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||
|
||||
|
@ -235,17 +338,24 @@ class AudioPanelRow(BlinkingSprite):
|
|||
self.selected = False
|
||||
self.stop_blinking()
|
||||
|
||||
def unsubscribe(self, callback=None, kind=None):
|
||||
if callback is None:
|
||||
callback = self.respond
|
||||
kind = pygame.MOUSEBUTTONDOWN
|
||||
GameChild.unsubscribe(self, self.respond, pygame.MOUSEBUTTONDOWN)
|
||||
self.play_button.unsubscribe()
|
||||
self.stop_button.unsubscribe()
|
||||
for spinner in self.volume_spinner, self.fade_out_spinner, self.loops_spinner, self.maxtime_spinner:
|
||||
spinner.unsubscribe()
|
||||
|
||||
def build(self):
|
||||
font = pygame.font.Font(
|
||||
self.get_resource(self.get_configuration("audio", "panel-font")),
|
||||
self.FONT_SIZE)
|
||||
ds = self.get_display_surface()
|
||||
dsr = ds.get_rect()
|
||||
surface = pygame.Surface((dsr.w * self.WIDTH, self.HEIGHT), pygame.SRCALPHA)
|
||||
surface.fill(self.BACKGROUND)
|
||||
self.add_frame(surface)
|
||||
name_sprite = Sprite(self)
|
||||
name = font.render(self.key + ":", True, self.FOREGROUND)
|
||||
name = self.font.render(self.key + ":", True, self.FOREGROUND)
|
||||
if name.get_width() > int(self.location.w * self.MAX_NAME_WIDTH):
|
||||
crop = pygame.Rect(0, 0, int(self.location.w * self.MAX_NAME_WIDTH), name.get_height())
|
||||
crop.right = name.get_rect().right
|
||||
|
@ -263,7 +373,7 @@ class AudioPanelRow(BlinkingSprite):
|
|||
file_sprite.location.midright = self.location.right - self.INDENT, self.location.centery
|
||||
file_sprite.display_surface = surface
|
||||
file_name_sprite = Sprite(self)
|
||||
file_name_text = font.render(self.get_sound_effect().path, True, self.FOREGROUND)
|
||||
file_name_text = self.font.render(self.get_sound_effect().path, True, self.FOREGROUND)
|
||||
file_name_sprite.add_frame(file_name_text)
|
||||
file_name_sprite.display_surface = box
|
||||
file_name_sprite.location.midright = file_sprite.location.w - self.INDENT, file_sprite.location.h / 2
|
||||
|
@ -273,6 +383,34 @@ class AudioPanelRow(BlinkingSprite):
|
|||
def get_sound_effect(self):
|
||||
return self.get_game().get_audio().sfx[self.key]
|
||||
|
||||
def update_config(self):
|
||||
if not self.get_configuration().has_section("sfx"):
|
||||
self.get_configuration().add_section("sfx")
|
||||
sound_effect = self.get_sound_effect()
|
||||
self.get_configuration().set(
|
||||
"sfx", self.key, "{}, {:.2f}, {:.2f}, {}, {:.2f}".format(
|
||||
sound_effect.path, sound_effect.local_volume, sound_effect.fade_out_length,
|
||||
sound_effect.loops, sound_effect.maxtime))
|
||||
config_path = self.get_configuration().locate_project_config_file()
|
||||
backup_path = config_path + ".backup"
|
||||
shutil.copyfile(config_path, backup_path)
|
||||
self.get_configuration().write(open(config_path, "w"))
|
||||
|
||||
def update(self):
|
||||
self.volume_spinner.location.midleft = self.location.move(5, 0).midright
|
||||
self.fade_out_spinner.location.midleft = self.volume_spinner.location.midright
|
||||
self.loops_spinner.location.midleft = self.fade_out_spinner.location.midright
|
||||
self.maxtime_spinner.location.midleft = self.loops_spinner.location.midright
|
||||
self.play_button.location.midleft = self.maxtime_spinner.location.move(5, 0).midright
|
||||
self.stop_button.location.midleft = self.play_button.location.midright
|
||||
Sprite.update(self)
|
||||
self.volume_spinner.update()
|
||||
self.fade_out_spinner.update()
|
||||
self.loops_spinner.update()
|
||||
self.maxtime_spinner.update()
|
||||
self.play_button.update()
|
||||
self.stop_button.update()
|
||||
|
||||
|
||||
class AudioPanelFileBrowser(Sprite):
|
||||
|
||||
|
@ -280,16 +418,10 @@ class AudioPanelFileBrowser(Sprite):
|
|||
HEIGHT = .75
|
||||
COLORS = pygame.Color(255, 255, 255), pygame.Color(0, 0, 0)
|
||||
HOME, UP = "[HOME]", "[UP]"
|
||||
FONT_SIZE = 16
|
||||
VOLUME_WIDTH = .1
|
||||
VOLUME_INDICATOR_HEIGHT = .1
|
||||
VOLUME_STEP = .05
|
||||
|
||||
def __init__(self, parent):
|
||||
Sprite.__init__(self, parent)
|
||||
self.font = pygame.font.Font(
|
||||
self.get_resource(self.get_configuration("audio", "panel-font")),
|
||||
self.FONT_SIZE)
|
||||
self.font = self.parent.font_large
|
||||
ds = self.get_display_surface()
|
||||
dsr = ds.get_rect()
|
||||
surface = pygame.Surface((dsr.w * self.WIDTH - 2, dsr.h * self.HEIGHT - 2), SRCALPHA)
|
||||
|
@ -297,23 +429,6 @@ class AudioPanelFileBrowser(Sprite):
|
|||
self.background = get_boxed_surface(surface, self.COLORS[0], self.COLORS[1])
|
||||
self.add_frame(self.background.copy())
|
||||
self.location.center = dsr.center
|
||||
self.volume_buttons = []
|
||||
for text in "VOL -", "VOL +":
|
||||
button = Sprite(self)
|
||||
button.add_frame(render_box(
|
||||
self.font, text, color=self.COLORS[1], background=self.COLORS[0],
|
||||
border=self.COLORS[1], width=self.VOLUME_WIDTH * dsr.w))
|
||||
button.location.top = self.location.bottom - 1
|
||||
self.volume_buttons.append(button)
|
||||
self.volume_buttons[0].location.left = self.location.left
|
||||
self.volume_buttons[1].location.right = self.location.right
|
||||
self.volume_indicator = Sprite(self)
|
||||
self.volume_indicator.add_frame(pygame.Surface((
|
||||
self.location.w - self.volume_buttons[0].location.w * 2,
|
||||
self.volume_buttons[0].location.h), SRCALPHA))
|
||||
self.volume_indicator.get_current_frame().fill(self.COLORS[0])
|
||||
self.volume_indicator.location.topleft = (
|
||||
self.volume_buttons[0].location.right, self.location.bottom - 1)
|
||||
self.reset()
|
||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||
|
||||
|
@ -324,11 +439,7 @@ class AudioPanelFileBrowser(Sprite):
|
|||
def respond(self, event):
|
||||
if not self.is_hidden():
|
||||
if event.button == 1:
|
||||
if self.volume_buttons[0].collide(event.pos):
|
||||
self.adjust_volume(-self.VOLUME_STEP)
|
||||
elif self.volume_buttons[1].collide(event.pos):
|
||||
self.adjust_volume(self.VOLUME_STEP)
|
||||
elif self.collide(event.pos):
|
||||
if self.collide(event.pos):
|
||||
for row in self.rows:
|
||||
if row.collide(Vector(*event.pos).get_moved(-self.location.left, -self.location.top)):
|
||||
full_path = os.path.join(os.path.sep.join(self.trail), row.path)
|
||||
|
@ -336,9 +447,9 @@ class AudioPanelFileBrowser(Sprite):
|
|||
os.path.isdir(full_path) and os.access(full_path, os.R_OK):
|
||||
self.visit(row.path)
|
||||
elif os.path.isfile(full_path) and os.access(full_path, os.R_OK):
|
||||
key = self.parent.get_selected().key
|
||||
if self.get_audio().load_sfx_file(full_path, key, True):
|
||||
self.update_config(key, full_path)
|
||||
selected = self.parent.get_selected()
|
||||
if self.get_audio().load_sfx_file(full_path, selected.key, True):
|
||||
selected.update_config()
|
||||
self.hide()
|
||||
self.get_delegate().cancel_propagation()
|
||||
self.parent.build()
|
||||
|
@ -350,27 +461,6 @@ class AudioPanelFileBrowser(Sprite):
|
|||
elif event.button == 5:
|
||||
self.row_offset += 1
|
||||
|
||||
def adjust_volume(self, step):
|
||||
selected = self.parent.get_selected()
|
||||
sound_effect = selected.get_sound_effect()
|
||||
print(sound_effect)
|
||||
sound_effect.adjust_volume(step)
|
||||
# sound_effect.set_volume(.1)
|
||||
print(sound_effect.get_volume())
|
||||
sound_effect.play()
|
||||
self.update_config(selected.key, sound_effect.path)
|
||||
|
||||
def update_config(self, key, path):
|
||||
if not self.get_configuration().has_section("sfx"):
|
||||
self.get_configuration().add_section("sfx")
|
||||
volume = self.get_audio().sfx[key].initial_volume
|
||||
print(self.get_audio().sfx[key])
|
||||
self.get_configuration().set("sfx", key, "{}, {}".format(path, volume))
|
||||
config_path = self.get_configuration().locate_project_config_file()
|
||||
backup_path = config_path + ".backup"
|
||||
shutil.copyfile(config_path, backup_path)
|
||||
self.get_configuration().write(open(config_path, "w"))
|
||||
|
||||
def hide(self):
|
||||
for row in self.parent.rows:
|
||||
row.selected = False
|
||||
|
@ -430,12 +520,105 @@ class AudioPanelFileBrowser(Sprite):
|
|||
index += 1
|
||||
for row in self.rows:
|
||||
row.update()
|
||||
self.volume_indicator.get_current_frame().fill(self.COLORS[0])
|
||||
self.volume_indicator.get_current_frame().fill(
|
||||
self.COLORS[1],
|
||||
(0, 0, self.volume_indicator.location.w * self.parent.get_selected().get_sound_effect().initial_volume,
|
||||
self.volume_indicator.location.h))
|
||||
self.volume_indicator.update()
|
||||
for button in self.volume_buttons:
|
||||
button.update()
|
||||
Sprite.update(self)
|
||||
|
||||
|
||||
class AudioPanelSpinner(Sprite):
|
||||
|
||||
def __init__(self, parent, font, label_font, width=80, height=48,
|
||||
magnitude=1, value=0, callback=None,
|
||||
foreground=pygame.Color(0, 0, 0),
|
||||
background=pygame.Color(255, 255, 255), precision=0,
|
||||
label_text=""):
|
||||
Sprite.__init__(self, parent)
|
||||
self.magnitude, self.value = magnitude, value
|
||||
self.background, self.foreground = background, foreground
|
||||
self.precision = precision
|
||||
self.callback = callback
|
||||
self.font = font
|
||||
self.label_font = label_font
|
||||
surface = pygame.Surface((width, height), SRCALPHA)
|
||||
surface.fill(background)
|
||||
self.add_frame(surface)
|
||||
self.label = Sprite(self)
|
||||
self.label.add_frame(self.label_font.render(label_text, True, foreground))
|
||||
self.label.display_surface = self.get_current_frame()
|
||||
self.display = Sprite(self)
|
||||
self.display.display_surface = self.get_current_frame()
|
||||
self.update_display()
|
||||
self.up_button = Sprite(self)
|
||||
self.up_button.add_frame(render_box(
|
||||
width=width - self.display.location.w - 2, height=int(height * .5) - 2,
|
||||
color=foreground, border=foreground, font=self.font, text="+"))
|
||||
self.up_button.location.left = self.display.location.right - 1
|
||||
self.up_button.display_surface = self.get_current_frame()
|
||||
self.down_button = Sprite(self)
|
||||
self.down_button.add_frame(render_box(
|
||||
width=self.up_button.location.w - 2, height=self.up_button.location.h - 1,
|
||||
border=foreground, font=self.font, text="-"))
|
||||
self.down_button.location.topleft = self.display.location.right - 1, \
|
||||
self.up_button.location.bottom - 1
|
||||
self.down_button.display_surface = self.get_current_frame()
|
||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||
|
||||
def unsubscribe(self, callback=None, kind=None):
|
||||
if callback is None:
|
||||
callback = self.respond
|
||||
kind = pygame.MOUSEBUTTONDOWN
|
||||
GameChild.unsubscribe(self, callback, kind)
|
||||
|
||||
def update_display(self):
|
||||
self.display.clear_frames()
|
||||
self.display.add_frame(render_box(
|
||||
width=int(self.location.w * .7) - 2,
|
||||
border=self.foreground, font=self.font, text="{:.{precision}f}".format(
|
||||
self.value, precision=self.precision)))
|
||||
self.display.location.bottomleft = 0, self.location.h
|
||||
|
||||
def increment(self, up=True):
|
||||
step = self.magnitude * [-1, 1][up]
|
||||
self.value += step
|
||||
if self.callback is not None:
|
||||
response = self.callback(step)
|
||||
if response is not None:
|
||||
self.value = response
|
||||
self.update_display()
|
||||
|
||||
def respond(self, event):
|
||||
if event.button == 1:
|
||||
relative_position = Vector(*event.pos).get_moved(
|
||||
-self.location.left, -self.location.top)
|
||||
up_collides = self.up_button.collide(relative_position)
|
||||
down_collides = self.down_button.collide(relative_position)
|
||||
if up_collides or down_collides:
|
||||
if up_collides:
|
||||
self.increment()
|
||||
else:
|
||||
self.increment(False)
|
||||
self.parent.update_config()
|
||||
|
||||
def update(self):
|
||||
self.get_current_frame().fill(self.background)
|
||||
self.label.update()
|
||||
self.up_button.update()
|
||||
self.down_button.update()
|
||||
self.display.update()
|
||||
Sprite.update(self)
|
||||
|
||||
|
||||
class AudioPanelButton(Sprite):
|
||||
|
||||
def __init__(self, parent, callback):
|
||||
Sprite.__init__(self, parent)
|
||||
self.callback = callback
|
||||
self.subscribe(self.respond, pygame.MOUSEBUTTONDOWN)
|
||||
|
||||
def unsubscribe(self, callback=None, kind=None):
|
||||
if callback is None:
|
||||
callback = self.respond
|
||||
kind = pygame.MOUSEBUTTONDOWN
|
||||
Sprite.unsubscribe(self, callback, kind)
|
||||
|
||||
def respond(self, event):
|
||||
if event.button == 1 and self.collide(event.pos):
|
||||
self.callback()
|
||||
|
|
|
@ -185,21 +185,25 @@ def get_boxed_surface(surface, background=None, border=None, border_width=1,
|
|||
surface = bordered_surface
|
||||
return surface
|
||||
|
||||
def render_box(font, text, antialias=True, color=(0, 0, 0), background=None, border=None,
|
||||
def render_box(font=None, text=None, antialias=True, color=(0, 0, 0), background=None, border=None,
|
||||
border_width=1, padding=0, width=None, height=None):
|
||||
surface = font.render(text, antialias, color, background)
|
||||
if width is not None or height is not None:
|
||||
if width is None:
|
||||
width = surface.get_width()
|
||||
if height is None:
|
||||
height = surface.get_height()
|
||||
container = Surface((width, height), SRCALPHA)
|
||||
if background is not None:
|
||||
container.fill(background)
|
||||
text_rect = surface.get_rect()
|
||||
text_rect.center = container.get_rect().center
|
||||
container.blit(surface, text_rect)
|
||||
surface = container
|
||||
if font is not None:
|
||||
surface = font.render(text, antialias, color, background)
|
||||
if width is not None or height is not None:
|
||||
if width is None:
|
||||
width = surface.get_width()
|
||||
if height is None:
|
||||
height = surface.get_height()
|
||||
container = Surface((width, height), SRCALPHA)
|
||||
if background is not None:
|
||||
container.fill(background)
|
||||
text_rect = surface.get_rect()
|
||||
text_rect.center = container.get_rect().center
|
||||
container.blit(surface, text_rect)
|
||||
surface = container
|
||||
else:
|
||||
surface = pygame.Surface((width, height), SRCALPHA)
|
||||
surface.fill(background)
|
||||
return get_boxed_surface(surface, background, border, border_width, padding)
|
||||
|
||||
def get_wrapped_text_surface(font, text, width, antialias, color,
|
||||
|
|
Loading…
Reference in New Issue