Page MenuHomePhorge

No OneTemporary

diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,88 +1,90 @@
@%@~LICENSE:OK~@%@
+saw_053122_2 - [opeth] Ack: all tools basically working (no text or group yet).
+
saw_053122_1 - [opeth] Fixing ack tooling: color, rect, and ellipse so far.
saw_053022_1 - [kaczynski] Color palette for ack.
saw_052822_1 - [ledzeppelin] More ack work.
saw_052722_3 - [ledzeppelin] Ack copy/paste (requires xclip system utility).
saw_052722_2 - [gojira] Ack save.
saw_052722_1 - [bach] A little bit of cleanup in ack classes.
saw_052622_5 - [bach] Implement ack Rect and Ellipse tools and Delete function.
saw_052622_4 - [bach] Add some color choices to ack.
saw_052622_3 - [bach] Begin to implement tools and objects in ack.
saw_052622_2 - [beethoven] Now have working captions filter in player rack.
saw_052622_1 - [beethoven] Implement keywords and labels in player rack. Add
ability to hide labels globally.
saw_052522_3 - [labyrinth] Improved confirmation/error dialogs.
saw_052522_2 - [labyrinth] Implemented a "list all" function for HotKeys.
saw_052522_1 - [labyrinth] Finished HotKeys panel for player.
saw_052422_1 - [labyrinth] Starting to implement HotKeys panel.
saw_052322_2 - [polog] More work on player rack. Starting to implement ack
(blackboard). Minor UI tweaks such as new status modes and
cursors. Improved escape key handling.
saw_052322_1 - [polog] Starting to implement player rack.
saw_052122_2 - [yelawolf] Remove the UNIQUE constraint on caption start time
because some files are actually marked with multiple captions
occurring at the same time. Add some more deferred downloads.
saw_052122_1 - [yelawolf] Implemented deferred downloads and seeded the database
with some videos. Beginning of a label system for tagging videos.
Channels, videos, and labels added by the user now start at
id=1000 to leave room for seeded entries. Database now enforces
foreign key constraints and patches use transactions. We now
perform a VACUUM operation on the database after patching or
application exit. Player explicitly disables key repeat on key
press. Debug DIP switch has been changed to the plus sign (+).
saw_051622_2 - [nin] Partial implementation of full-screen mode without meta.
saw_051622_1 - [nin] Improve database performance. Moved audio extraction step
to the main video download routine so we no longer have to wait
for audio extraction upon first play.
saw_051522_1 - [nin] Add switch.py to easily start with DIP switches set.
saw_042422_1 - [controldenied] Beginning to get replay captures to play.
saw_042222_1 - [controldenied] Reworking the replay system so we can now
capture keyboard and mouse actions. The command-line options
(dip switches) should now be specified as the first option only
and without spaces.
saw_041222_1 - [theprodigy] Minor changes wrap up this series.
saw_040822_1 - [theprodigy] Just a little bit better.
saw_040722_1 - [theprodigy] Introducing: ImageEngine (imagine)! Add more
command-line options (see README). Status bar now with separate
UIManager (sui). Player NUM-pad key improvements. Get FPS/avg
score readouts with TAB key.
saw_040422_1 - We now have a working sequence/segment editor.
saw_040222_1 - Implemented replay system. Improved player performance.
saw_033022_2 - Fix kush prompt paint (cursor overlap problem).
saw_033022_1 - Migration to the media/fragment system and versioned database.
saw_032622_2 - Rename directories.
saw_032622_1 - First commit.
diff --git a/k/ack/__init__.py b/k/ack/__init__.py
--- a/k/ack/__init__.py
+++ b/k/ack/__init__.py
@@ -1,404 +1,409 @@
from k.ui import *
import k.storage as media
from k.player.ui import PRECT
+from .tool.color import Tool as Color
+from .tool.wiggle import Tool as Wiggle
from .tool.rect import Tool as Rect
-from .tool.color import Tool as Color
from .tool.ellipse import Tool as Ellipse
-#from .adjust import Tool as Adjust
-#from .brush import Tool as Brush
+from .tool.adjust import Tool as Adjust
from .obj import Null, Image
from .obj.draw import Selector
from datetime import datetime
class Blackboard:
def __init__(self, k):
self.k = k
self.back_black = pygame.Surface((WIDTH, HEIGHT-STATUS-1))
self.back_black.fill(BLACK)
self.back_white = pygame.Surface((WIDTH, HEIGHT-STATUS-1))
self.back_white.fill(WHITE)
self.back = self.back_black
self.surf = pygame.Surface((WIDTH, HEIGHT-STATUS-1), pygame.SRCALPHA)
self.objects = [ ]
self.selects = [ ]
self.selecting = None
self.overlay = None
self.colors = [
None, # special "diverting" color
- WHITE,
+ GRAY,
+ CYAN,
+ MAGENTA,
+ YELLOW,
RED,
GREEN,
BLUE,
- CYAN,
- MAGENTA,
- YELLOW,
- GRAY,
+ WHITE,
BLACK,
]
self.tools = {
+ pygame.K_BACKQUOTE: Color(self),
+ pygame.K_w: Wiggle(self),
pygame.K_r: Rect(self),
- pygame.K_BACKQUOTE: Color(self),
pygame.K_e: Ellipse(self),
- #pygame.K_a: Adjust(self),
- #pygame.K_b: Brush(self),
+ pygame.K_a: Adjust(self),
}
self.tool = None
self.tooling = None
- self.tool_pick(self.tools[pygame.K_r])
+ self.tool_pick(self.tools[pygame.K_w])
self.start = None
self.pos = None
self.control = False
self.select = False
self.paint_back()
def add_obj(self, obj):
self.objects.append(obj)
if isinstance(obj, Selector):
if not self.selects:
self.selecting = [Clock(Selector.FPS), Selector.MAX, True, True]
self.selects.append(len(self.objects) - 1)
if self.back is self.back_black:
obj.key(BLACK)
obj.color(WHITE)
else:
obj.key(WHITE)
obj.color(BLACK)
return obj
def del_obj(self):
if not self.objects:
return None
obj = self.objects.pop()
if isinstance(obj, Selector):
self.selects.pop()
if not self.selects:
self.selecting = None
return obj
def set_obj(self, obj):
self.del_obj()
return self.add_obj(obj)
def obj(self):
if not self.objects:
return None
return self.objects[-1]
def tool_pick(self, tool, cancel=False):
print(f'tool_pick: {tool}')
if self.tooling:
if self.tool_stop() and cancel:
self.del_obj()
prev_tool = self.tool
self.tool = tool
prev_overlay = self.overlay
self.overlay = tool.pick(prev_tool)
if self.overlay:
self.paint_overlay()
elif prev_overlay:
self.paint_back()
self.paint_surf()
if self.tooling:
self.tool.start(self.start if cancel else self.pos)
def tool_start(self, pos):
self.start = pos
self.last_obj = self.obj()
self.tool.start(self.start)
def tool_stop(self):
self.tool.stop()
obj = self.obj()
if not obj or obj is self.last_obj:
return False
size = obj.size()
if size[0] < 1 or size[1] < 1:
self.del_obj()
return False
else:
return True
def tool_at(self, pos):
self.pos = pos
paint = self.tool.use(self.pos, self.tooling == pygame.BUTTON_MIDDLE)
if paint:
self.paint() #FIXME
else:
if self.overlay:
self.paint_back()
self.paint_surf()
#elif area is not None:
# self.paint_obj((area[0], area[1]), area)
# self.paint_surf((area[0], area[1]), area)
return paint
def paint(self):
#print('ack full paint')
if self.overlay:
self.paint_overlay()
else:
self.paint_back()
self.surf = pygame.Surface((WIDTH, HEIGHT-STATUS-1),
pygame.SRCALPHA)
self.paint_objects()
self.paint_surf()
def paint_back(self):
self.k.blit(self.back, (0, 0))
def paint_objects(self):
for obj in self.objects:
show = True
if isinstance(obj, Null):
show = False
elif isinstance(obj, Selector):
show = self.select or self.selecting[3]
if show:
# FIXME: use blits() here?
self.surf.blit(obj.surf, obj.pos)
#def paint_obj(self, pos=None, area=None):
# self.surf.blit(self.objects[-1][0], pos if pos else (0, 0), area)
#def paint_surf(self, pos=None, area=None):
# #print(f'paint_surf: {pos} -> {area}')
# self.k.blit(self.surf, pos if pos else (0, 0), area)
def paint_surf(self, area=None):
self.k.blit(self.surf, (0, 0), area)
def paint_overlay(self):
self.k.blit(self.overlay, (0, 0))
def tick(self):
if self.k.player.is_playing(True):
self.paint_surf((PRECT[0], PRECT[1]), PRECT)
#if not self.tooling and self.objects:
# for obj in self.objects:
# obj.surf.set_palette_at(9, CYAN)
if not self.tooling and self.selecting and self.selecting[3]:
clock = self.selecting[0]
clock.tick()
if clock.ready():
val = self.selecting[1]
rev = self.selecting[2]
if rev:
val -= Selector.STEP
if val < Selector.MIN:
val = Selector.MIN
rev = False
else:
val += Selector.STEP
if val > Selector.MAX:
val = Selector.MAX
rev = True
self.selecting[1] = val
self.selecting[2] = rev
for idx in self.selects:
self.objects[idx].alpha(val)
self.paint()
def kick(self, event):
#print(f'ack kick: {event}')
if event.type == pygame.WINDOWFOCUSGAINED \
or event.type == pygame.WINDOWEXPOSED:
self.paint()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == pygame.BUTTON_LEFT \
or event.button == pygame.BUTTON_MIDDLE:
if not self.tooling:
self.tooling = event.button
self.tool_start(event.pos)
self.tool_at(event.pos)
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == self.tooling:
self.tool_stop()
self.tooling = None
if self.overlay:
self.paint_overlay()
+ else:
+ self.paint()
+
elif event.button == pygame.BUTTON_WHEELUP:
self.tool.up()
if self.tooling:
self.tool_at(event.pos)
elif event.button == pygame.BUTTON_WHEELDOWN:
self.tool.down()
if self.tooling:
self.tool_at(event.pos)
elif event.type == pygame.MOUSEMOTION:
if self.tooling:
self.tool_at(event.pos)
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL or event.key == pygame.K_RCTRL:
self.control = True
+ self.tool.constraints()
if self.tooling:
self.tool_at(self.pos)
elif event.key == pygame.K_LSHIFT or event.key == pygame.K_RSHIFT:
self.select = True
self.tool.selector()
paint = True
if self.tooling:
if self.tool_at(self.pos):
paint = False
if paint:
self.paint()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LCTRL or event.key == pygame.K_RCTRL:
self.control = False
+ self.tool.constraints()
if self.tooling:
self.tool_at(self.pos)
elif event.key == pygame.K_LSHIFT or event.key == pygame.K_RSHIFT:
self.select = False
self.tool.selector()
paint = True
if self.tooling:
if self.tool_at(self.pos):
paint = False
if paint:
self.paint()
elif event.key in self.tools:
tool = self.tools[event.key]
if tool is self.tool:
tool = tool.toggle()
if tool:
self.tool_pick(tool)
if self.tooling:
self.tool_at(self.pos)
else:
self.tool_pick(tool, True)
if self.tooling:
self.tool_at(self.pos)
elif event.unicode >= '1' and event.unicode <= '9':
self.tool.choice(1 + ord(event.unicode) - ord('1'))
if self.tooling:
self.tool_at(self.pos)
elif event.key == pygame.K_0:
self.tool.choice(0)
if self.tooling:
self.tool_at(self.pos)
elif event.key == pygame.K_b:
if self.back is self.back_black:
self.back = self.back_white
skey = WHITE
scolor = BLACK
else:
self.back = self.back_black
skey = BLACK
scolor = WHITE
for idx in self.selects:
obj = self.objects[idx]
obj.key(skey)
obj.color(scolor)
self.paint()
elif event.key == pygame.K_SPACE:
if self.selecting:
self.selecting[3] = not self.selecting[3]
self.paint()
- #elif event.key == pygame.K_d:
- # if self.objects:
- # self.del_obj()
- # self.paint()
+ elif event.key == pygame.K_d:
+ if self.objects:
+ self.del_obj()
+ self.paint()
elif event.key == pygame.K_s:
name = file_date_time(datetime.now())
print(f'saving: {name}')
media.save_ack_image(self.surf, name)
#FIXME: use subsurface here instead:
screen = pygame.Surface((WIDTH, HEIGHT-STATUS-1))
screen.blit(self.k.screen, (0, 0))
media.save_ack_image(screen, f'{name}_combined')
elif event.key == pygame.K_c:
obj = self.obj()
if obj:
#with BytesIO() as io:
# pygame.image.save(obj[0], io, 'png')
# try:
# pygame.scrap.put('image/png', io.getvalue())
#
# except pygame.error:
# fn = media.clipboard(io.getvalue())
# pygame.scrap.put('text/plain;charset=utf-8',
# bytes(f'file://{fn}', 'UTF-8'))
media.put_clipboard_image(obj.surf)
elif event.key == pygame.K_v:
print('clipboard contents:')
#for mtype in pygame.scrap.get_types():
# print(f' {mtype}')
# if 'text' in mtype:
# print(f' {pygame.scrap.get(mtype)}')
surf = media.get_clipboard_image()
if surf is not None:
self.add_obj(Image(surf))
self.paint()
def kill(self):
pass
diff --git a/k/ack/obj/draw.py b/k/ack/obj/draw.py
--- a/k/ack/obj/draw.py
+++ b/k/ack/obj/draw.py
@@ -1,68 +1,93 @@
from k.ui import *
from . import Object
from abc import ABC
+from math import ceil
class Drawable(Object, ABC):
IDX_KEY = 0
IDX_COLOR = 9
def __init__(self, pos, size):
try:
super().__init__(pos, pygame.Surface(size, depth=8))
except pygame.error as e:
print(f'size: {size}')
raise e
self.surf.set_colorkey(self.IDX_KEY)
self.surf.fill(self.IDX_KEY)
def key(self, color):
self.surf.set_palette_at(self.IDX_KEY, color)
def rect(self, border=0, rounded=False):
size = self.size()
pygame.draw.rect(
self.surf, self.IDX_COLOR, pygame.Rect((0, 0), size),
border // 2 if rounded else border,
border // 2 if rounded else 0)
return self
def ellipse(self, border=0):
size = self.size()
pygame.draw.ellipse(
self.surf, self.IDX_COLOR, pygame.Rect((0, 0), size), border)
return self
+ def blit(self, obj):
+ self.surf.blit(obj.surf, (0, 0))
+ return self
+
+ def blot(self, pos, size, rounded=False):
+ if rounded:
+ pygame.draw.circle(
+ self.surf, self.IDX_COLOR, pos, ceil(size/2))
+
+ else:
+ pygame.draw.rect(
+ self.surf, self.IDX_COLOR, pygame.Rect(
+ (pos[0] - round(size/2), pos[1] - round(size/2)),
+ (size, size)))
+
+ return self
+
+ def line(self, pos_from, pos_to, size):
+ #print(f'line: {pos_from} -> {pos_to}')
+ pygame.draw.line(
+ self.surf, self.IDX_COLOR, pos_from, pos_to, size)
+
+ return self
+
class Drawing(Drawable):
def __init__(self, pos, size, color):
super().__init__(pos, size)
self.color = color
self.key(BLACK if color != BLACK else WHITE)
self.surf.set_palette_at(self.IDX_COLOR, self.color)
class Selector(Drawable):
FPS = 27
STEP = 9
MIN = 42
MAX = 128
def __init__(self, pos, size):
super().__init__(pos, size)
self.alpha(self.MAX)
def color(self, color):
self.surf.set_palette_at(self.IDX_COLOR, color)
def alpha(self, alpha):
self.surf.set_alpha(alpha)
diff --git a/k/ack/tool/__init__.py b/k/ack/tool/__init__.py
--- a/k/ack/tool/__init__.py
+++ b/k/ack/tool/__init__.py
@@ -1,80 +1,107 @@
from k.ui import *
from ..obj.draw import Drawing, Selector
from abc import ABC, abstractmethod
class Tool(ABC):
def __init__(self, ack):
self.ack = ack
@abstractmethod
def pick(self, prev):
pass
def toggle(self):
pass
def selector(self):
pass
+ def constraints(self):
+ pass
+
def choice(self, c):
pass
def up(self):
pass
def down(self):
pass
def start(self, pos):
pass
def stop(self):
pass
@abstractmethod
def use(self, pos, middle=False):
pass
- def draw_select(self, pos, middle_out):
+
+class Draws(Tool, ABC):
+ def __init__(self, ack, choice=1, size=0):
+ self.ack = ack
+
+ self.choice(choice)
+ self.size = size
+
+ def choice(self, c):
+ self.color = self.ack.colors[c]
+
+ def up(self):
+ self.size += 1
+ if self.size > WIDTH:
+ self.size = WIDTH
+
+ def down(self):
+ self.size -= 1
+ if self.size < 0:
+ self.size = 0
+
+ def draw_select(self, pos, middle_out, constrain=None):
x = self.ack.start[0]
y = self.ack.start[1]
w = pos[0] - x
h = pos[1] - y
- flip_x = False
- flip_y = False
+ self.flip_x = False
+ self.flip_y = False
if w < 0:
w = abs(w)
x -= w
- flip_x = True
+ self.flip_x = True
if h < 0:
h = abs(h)
y -= h
- flip_y = True
+ self.flip_y = True
if middle_out:
w *= 2
h *= 2
- x = pos[0] if flip_x else pos[0] - w
- y = pos[1] if flip_y else pos[1] - h
+ x = pos[0] if self.flip_x else pos[0] - w
+ y = pos[1] if self.flip_y else pos[1] - h
- if self.ack.control:
+ if constrain is None:
+ constrain = self.ack.control
+
+ if constrain:
normal = max(w, h)
if middle_out:
if w < h:
x -= (h - w)//2
elif h < w:
y -= (w - h)//2
w = normal
h = normal
return self.ack.set_obj(
Drawing((x, y), (w, h), self.color) \
if not self.ack.select else \
Selector((x, y), (w, h))
)
diff --git a/k/ack/adjust.py b/k/ack/tool/adjust.py
rename from k/ack/adjust.py
rename to k/ack/tool/adjust.py
--- a/k/ack/adjust.py
+++ b/k/ack/tool/adjust.py
@@ -1,28 +1,31 @@
from k.ui import *
-from .base import Tool as Base
+from . import Tool as Base
class Tool(Base):
def __init__(self, ack):
super().__init__(ack)
- def cursor(self):
+ def pick(self, prev):
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_HAND)
- def start(self):
- self.pos = self.ack.obj()[1]
+ def start(self, pos):
+ obj = self.ack.obj()
+ if not obj: return
+
+ self.pos = obj.pos
- def use(self, pos):
- start = self.ack.tool_start
+ def use(self, pos, middle):
+ obj = self.ack.obj()
+ if not obj: return
- self.ack.obj()[1] = (
+ start = self.ack.start
+
+ obj.pos = (
pos[0] - start[0] + self.pos[0],
pos[1] - start[1] + self.pos[1]
)
#return pygame.Rect((0, 0), (WIDTH, HEIGHT-STATUS-1)) #FIXME
- return True #FIXME
+ return obj
- def stop(self):
- pass
-
diff --git a/k/ack/tool/ellipse.py b/k/ack/tool/ellipse.py
--- a/k/ack/tool/ellipse.py
+++ b/k/ack/tool/ellipse.py
@@ -1,40 +1,21 @@
from k.ui import *
-from . import Tool as Base
+from . import Draws
from ..obj import Null
-class Tool(Base):
+class Tool(Draws):
def __init__(self, ack):
super().__init__(ack)
- self.choice(1)
- self.size = 1
-
def pick(self, prev):
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_CROSSHAIR)
- def choice(self, c):
- self.color = self.ack.colors[c]
-
- def up(self):
- self.size += 1
- if self.size > WIDTH:
- self.size = WIDTH
-
- def down(self):
- self.size -= 1
- if self.size < 0:
- self.size = 0
-
def start(self, pos):
self.ack.add_obj(Null())
def use(self, pos, middle=False):
return self.draw_select(
pos, middle
).ellipse(self.size)
- def stop(self):
- pass
-
diff --git a/k/ack/tool/rect.py b/k/ack/tool/rect.py
--- a/k/ack/tool/rect.py
+++ b/k/ack/tool/rect.py
@@ -1,41 +1,26 @@
from k.ui import *
-from . import Tool as Base
+from . import Draws
from ..obj import Null
-class Tool(Base):
+class Tool(Draws):
def __init__(self, ack):
super().__init__(ack)
self.rounded = False
- self.choice(1)
- self.size = 1
def pick(self, prev):
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_CROSSHAIR)
def toggle(self):
self.rounded = not self.rounded
- def choice(self, c):
- self.color = self.ack.colors[c]
-
- def up(self):
- self.size += 1
- if self.size > WIDTH:
- self.size = WIDTH
-
- def down(self):
- self.size -= 1
- if self.size < 0:
- self.size = 0
-
def start(self, pos):
self.ack.add_obj(Null())
def use(self, pos, middle=False):
return self.draw_select(
pos, middle
).rect(self.size, self.rounded)
diff --git a/k/ack/brush.py b/k/ack/tool/wiggle.py
rename from k/ack/brush.py
rename to k/ack/tool/wiggle.py
--- a/k/ack/brush.py
+++ b/k/ack/tool/wiggle.py
@@ -1,21 +1,76 @@
from k.ui import *
-from .base import Tool as Base
+from . import Draws
+from ..obj import Null
+from ..obj.draw import Drawing, Selector
-class Tool(Base):
+class Tool(Draws):
def __init__(self, ack):
- super().__init__(ack)
+ super().__init__(ack, size=4)
- def cursor(self):
+ self.rounded = True
+
+ def pick(self, prev):
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_CROSSHAIR)
- def start(self):
- self.ack.new_obj()
+ def toggle(self):
+ self.rounded = not self.rounded
+
+ def selector(self):
+ if self.ack.tooling:
+ obj = self.ack.obj()
+ size = obj.size()
+
+ return self.ack.set_obj(
+ Drawing(obj.pos, size, self.color) \
+ if not self.ack.select else \
+ Selector(obj.pos, size)
+
+ ).blit(obj)
+
+ def constraints(self):
+ if self.ack.tooling:
+ if self.ack.control:
+ self.ack.add_obj(Null())
+
+ else:
+ size = (WIDTH, HEIGHT-STATUS-1)
+ self.ack.add_obj(
+ Drawing((0, 0), size, self.color) \
+ if not self.ack.select else \
+ Selector((0, 0), size)
+
+ )
- def use(self, pos):
- return pygame.draw.circle(self.ack.obj()[0],
- self.ack.color, pos, self.ack.size)
+ def down(self):
+ super().down()
+ if self.size < 1:
+ self.size = 1
+
+ def start(self, pos):
+ self.constraints()
+ if not self.ack.control:
+ self.ack.obj().blot(pos, self.size, self.rounded)
+
+ def use(self, pos, middle=False):
+ if pos != self.ack.start:
+ if self.ack.control:
+ obj = self.draw_select(pos, middle, False)
+ size = obj.size()
+ obj.line(
+ (size[0] if self.flip_x else 0,
+ size[1] if self.flip_y else 0),
+ (size[0] if not self.flip_x else 0,
+ size[1] if not self.flip_y else 0),
+ self.size)
+
+ else:
+ obj = self.ack.obj()
+ obj.line(self.ack.start, pos, self.size)
+ self.ack.start = pos
+
+ return obj
def stop(self):
- pass
+ self.ack.obj().blot(self.ack.pos, self.size, self.rounded)
diff --git a/k/keys/ack.py b/k/keys/ack.py
--- a/k/keys/ack.py
+++ b/k/keys/ack.py
@@ -1,87 +1,100 @@
from .base import *
class Panel(Keys):
def __init__(self, panel, anchors, container):
super().__init__(panel, anchors, container)
self.key(pygame.K_ESCAPE, 'Esc', size=KEY_TOP,
info='Close the blackboard.')
self.nop(pygame.K_F1, 'F1', (KEY[0], 0), KEY_TOP, left=pygame.K_ESCAPE)
self.nop(pygame.K_F2, 'F2', size=KEY_TOP, left=pygame.K_F1)
self.nop(pygame.K_F3, 'F3', size=KEY_TOP, left=pygame.K_F2)
self.nop(pygame.K_F4, 'F4', size=KEY_TOP, left=pygame.K_F3)
self.nop(pygame.K_F5, 'F5', (KEY[0]//2, 0), KEY_TOP, left=pygame.K_F4)
self.nop(pygame.K_F6, 'F6', size=KEY_TOP, left=pygame.K_F5)
self.nop(pygame.K_F7, 'F7', size=KEY_TOP, left=pygame.K_F6)
- self.nop(pygame.K_BACKQUOTE, '`', (0, GAP_TOP), top=pygame.K_ESCAPE)
+ self.key(pygame.K_BACKQUOTE, '`', (0, GAP_TOP), top=pygame.K_ESCAPE,
+ info='Use the Color tool (toggle palette).')
self.key(pygame.K_1, '1', (0, GAP_TOP), left=pygame.K_BACKQUOTE,
info='Choose color #1.')
self.key(pygame.K_2, '2', (0, GAP_TOP), left=pygame.K_1,
info='Choose color #2.')
self.key(pygame.K_3, '3', (0, GAP_TOP), left=pygame.K_2,
info='Choose color #3.')
self.key(pygame.K_4, '4', (0, GAP_TOP), left=pygame.K_3,
info='Choose color #4.')
self.key(pygame.K_5, '5', (0, GAP_TOP), left=pygame.K_4,
info='Choose color #5.')
self.key(pygame.K_6, '6', (0, GAP_TOP), left=pygame.K_5,
info='Choose color #6.')
self.key(pygame.K_7, '7', (0, GAP_TOP), left=pygame.K_6,
info='Choose color #7.')
self.key(pygame.K_8, '8', (0, GAP_TOP), left=pygame.K_7,
info='Choose color #8.')
self.key(pygame.K_9, '9', (0, GAP_TOP), left=pygame.K_8,
info='Choose color #9.')
self.nop(pygame.K_TAB, 'Tab', size=KEY[0]//2, top=pygame.K_BACKQUOTE)
- self.nop(pygame.K_q, 'Q', left=pygame.K_TAB)
- self.nop(pygame.K_w, 'W', left=pygame.K_q)
+ self.key(pygame.K_q, 'Q', left=pygame.K_TAB,
+ info='Use the Queue&Query tool.')
+ self.key(pygame.K_w, 'W', left=pygame.K_q,
+ info='Use the Wiggle tool.')
self.key(pygame.K_e, 'E', left=pygame.K_w,
info='Use the Ellipse tool.')
self.key(pygame.K_r, 'R', left=pygame.K_e,
info='Use the Rectangle tool.')
- self.nop(pygame.K_t, 'T', left=pygame.K_r)
+ self.key(pygame.K_t, 'T', left=pygame.K_r,
+ info='Use the Text tool.')
self.nop(pygame.K_y, 'Y', left=pygame.K_t)
self.nop(pygame.K_u, 'U', left=pygame.K_y)
self.nop(pygame.K_i, 'I', left=pygame.K_u)
self.nop(pygame.K_CAPSLOCK, 'CapsLock', size=KEY[0]//2+15,
top=pygame.K_TAB)
self.key(pygame.K_a, 'A', left=pygame.K_CAPSLOCK,
info='Use the Adjuster tool.')
self.key(pygame.K_s, 'S', left=pygame.K_a,
info='Save drawing.')
self.key(pygame.K_d, 'D', left=pygame.K_s,
info='Delete object.')
- self.nop(pygame.K_f, 'F', left=pygame.K_d)
- self.nop(pygame.K_g, 'G', left=pygame.K_f)
+ self.key(pygame.K_f, 'F', left=pygame.K_d,
+ info='Use the Fill tool.')
+ self.key(pygame.K_g, 'G', left=pygame.K_f,
+ info='Group.')
self.nop(pygame.K_h, 'H', left=pygame.K_g)
self.nop(pygame.K_j, 'J', left=pygame.K_h)
self.nop(pygame.K_k, 'K', left=pygame.K_j)
- self.nop(pygame.K_LSHIFT, 'Shift', size=KEY[0]+15,
- top=pygame.K_CAPSLOCK)
- self.nop(pygame.K_z, 'Z', left=pygame.K_LSHIFT)
- self.nop(pygame.K_x, 'X', left=pygame.K_z)
+ self.key(pygame.K_LSHIFT, 'Shift', size=KEY[0]+15,
+ top=pygame.K_CAPSLOCK, info=INFO_MOD)
+ self.key(pygame.K_z, 'Z', left=pygame.K_LSHIFT,
+ info='Undo.')
+ self.combo((pygame.K_LSHIFT, pygame.K_z),
+ info='Redo.')
+ self.combo((pygame.K_LCTRL, pygame.K_z),
+ info='Redo all.')
+ self.key(pygame.K_x, 'X', left=pygame.K_z,
+ info='Cut.')
self.key(pygame.K_c, 'C', left=pygame.K_x,
info='Copy object to clipboard.')
self.key(pygame.K_v, 'V', left=pygame.K_c,
info='Paste clipboard contents as new object.')
self.key(pygame.K_b, 'B', left=pygame.K_v,
- info='Use the Brush tool.')
+ info='Background toggle.')
self.nop(pygame.K_n, 'N', left=pygame.K_b)
self.nop(pygame.K_m, 'M', left=pygame.K_n)
- self.nop(pygame.K_LCTRL, 'Ctrl', size=KEY[0]//2, top=pygame.K_LSHIFT)
+ self.key(pygame.K_LCTRL, 'Ctrl', size=KEY[0]//2, top=pygame.K_LSHIFT,
+ info=INFO_MOD)
self.nop(pygame.K_LSUPER, 'Win', size=15, left=pygame.K_LCTRL)
self.nop(pygame.K_LALT, 'Alt', size=15, left=pygame.K_LSUPER)
self.nop(pygame.K_SPACE, 'Space', size=KEY[0]*5, left=pygame.K_LALT)
def title(self):
return 'ACK'
def descr(self):
return 'These keys apply when "ack" (blackboard) is active.'
diff --git a/k/ui.py b/k/ui.py
--- a/k/ui.py
+++ b/k/ui.py
@@ -1,364 +1,364 @@
import colorama as c
print('U.I. '+c.Fore.BLACK+c.Style.BRIGHT+'chaos'+c.Style.RESET_ALL+' begins')
import pygame
import pygame_gui
from contextlib import AbstractContextManager
import time
WIDTH = 1042
HEIGHT = 666
STATUS = 33 # status bar height
PWIDTH = 505 # player width
PHEIGHT = 284 # player height
MODES = {
'N': 'normal.png', # nothing specifically
'E': 'error.png', # something went wrong
'B': 'busy.png', # generic "doing something"
'D': 'txfr.png', # downloading
'A': 'ack.png', # blackboard
'K': 'keys.png', # keyboard discovery
'Q': 'quit.png', # quitting
'C': 'confirm.png', # confirmation required
}
LOG_DISABLE = [
'meta tick',
'meta kick',
'kush key',
]
BLACK = pygame.Color( 0, 0, 0)
WHITE = pygame.Color(255, 255, 255)
RED = pygame.Color(255, 0, 0)
GREEN = pygame.Color( 0, 255, 0)
BLUE = pygame.Color( 0, 0, 255)
CYAN = pygame.Color( 0, 255, 255)
MAGENTA = pygame.Color(255, 0, 255)
YELLOW = pygame.Color(255, 255, 0)
-GRAY = pygame.Color(128, 128, 128)
-GREY = GRAY
+GRAY = pygame.Color(127, 127, 127)
+GREY = pygame.Color(128, 128, 128) #gray "extra"
ORANGE = pygame.Color(255, 128, 0)
SPACER = pygame.Rect((10, 10), (-1, -1))
PANEL_SPACER = pygame.Rect((10, 10), (WIDTH-20, HEIGHT-100)) #FIXME
ANCHOR = {"left":"left", "top":"top", "right":"left", "bottom":"top"}
SAMPLE_RATE = 44100
PLAY_SEEK_VERT = 3
PLAY_SEEK_VERT_CTRL = 42
PLAY_SEEK_VERT_SHIFT = 666
PAUSE_SEEK_VERT = 1
PAUSE_SEEK_VERT_CTRL = 3333
PAUSE_SEEK_VERT_SHIFT = 10000
SEEK_HORIZ = 10
SEEK_HORIZ_CTRL = 100
SEEK_HORIZ_SHIFT = 1000
# A generic object
class Meta():
def __init__(self):
pass
def target(element, direction='left', anchors=ANCHOR):
anchors = anchors.copy()
anchors[direction+'_target'] = element
return anchors
def scroll_to_bottom(container):
scroll = container.vert_scroll_bar
if not scroll:
return
scroll.scroll_position = scroll.bottom_limit \
- scroll.sliding_button.relative_rect.height
scroll.start_percentage = scroll.scroll_position \
/ scroll.scrollable_height
scroll.has_moved_recently = True
scroll.redraw_scrollbar()
def hhmmss(secs, millis=False):
s = int(secs % 60)
m = int(secs / 60)
h = int(m / 60)
m = m % 60
if s < 10:
s = f'0{s}'
if m < 10:
m = f'0{m}'
if h < 10:
h = f'0{h}'
text = f'{h}:{m}:{s}'
if millis:
millis = int((secs % 1) * 1000)
text += f'.{millis}'
return text
def date_time(dt):
return dt.strftime('%Y-%m-%d %H:%M:%S')
def file_date_time(dt):
return dt.strftime('%Y-%m-%d_%H-%M-%S')
class KGUI(pygame_gui.UIManager):
def __init__(self, resolution):
super().__init__(resolution)
def set_focus_set(self, focus):
old_set = self.focused_set
super().set_focus_set(focus)
new_set = self.focused_set
fix_text = False
if old_set is not None:
for item in old_set:
if isinstance(item, pygame_gui.elements.UITextEntryLine):
fix_text = True
break
if fix_text:
if new_set is not None:
for item in new_set:
if isinstance(item, pygame_gui.elements.UITextEntryLine):
fix_text = False
break
if fix_text:
#print('resetting key repeat')
pygame.key.set_repeat(0)
class KPanel:
def __init__(self, k, anchors=None, container=None,
relative_rect=PANEL_SPACER, visible=0):
self.k = k
self.container = pygame_gui.core.UIContainer(
manager=k.gui,
container=container,
anchors=anchors,
relative_rect=relative_rect,
visible=visible)
def kill(self):
self.container.kill()
def show(self):
self.container.show()
def hide(self):
self.container.hide()
def keydown(self, key, mod):
return False
def keyup(self, key, mod):
return False
def click(self, element, target=None):
return False
def get_rect(self):
return self.container.get_relative_rect()
def set_position(self, pos):
self.container.set_relative_position(pos)
def move_by(self, dx, dy):
pos = self.get_rect()
x = pos[0] + dx
y = pos[1] + dy
self.set_position((x, y))
def panel_swap(self, btn, panel, kill=False):
if self.cur_btn: self.cur_btn.enable()
self.cur_btn = btn
if self.cur_btn: self.cur_btn.disable()
if self.cur_panel:
self.cur_panel.kill() if kill else self.cur_panel.hide()
self.cur_panel = panel
if self.cur_panel: self.cur_panel.show()
class Clock():
def __init__(self, fps=999):
self.fps = fps
self.reset()
def reset(self):
self.started = time.perf_counter()
self.last = self.started
self.last_frame = 0
def tick(self):
last = self.last
self.last = time.perf_counter()
return self.last - last
def ready(self):
next_frame = self._next_()
if self.last >= next_frame:
#self.last_frame = self.last
self._set_()
return True
else:
return False
def wait(self):
next_frame = self._next_()
now = time.perf_counter()
#print(f' {next_frame} {now}')
delta = next_frame - now
#print(f' {delta}')
if delta > 0:
#print('waiting')
time.sleep(delta)
self._set_()
def _next_(self):
frames = int((self.last_frame - self.started) * self.fps)
next_frame = self.started + ((frames + 1) / self.fps)
#print(f'{frames} {self.last} {self.last_frame} {next_frame}')
return next_frame
def _set_(self):
self.last_frame = time.perf_counter()
#def get(self):
# return 1 / (time.perf_counter() - self.last)
class NullClock(Clock):
def __init__(self):
super().__init__(fps=None)
def _next_(self):
return 0
class Counter(AbstractContextManager):
def __init__(self):
super().__init__()
self.score = [ ]
self.start()
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type=None, exc_value=None, traceback=None):
self.stop()
return None
def start(self):
self.started = time.perf_counter()
def stop(self):
now = time.perf_counter()
self.score.append((now, now - self.started))
cut = 0
for then, count in self.score:
if now - then < 15:
break
cut += 1
del self.score[:cut]
def score1(self):
return self._scoreX_(1)
def score5(self):
return self._scoreX_(5)
def score15(self):
return self._scoreX_(15)
def _scoreX_(self, x):
now = time.perf_counter()
entries = 0
score = 0
for then, count in reversed(self.score):
if now - then >= x:
break
entries += 1
score += count
return (entries/x, score/x)
@staticmethod
def _score_(score):
fc = c.Style.BRIGHT + f'{round(score[0])}' + c.Style.RESET_ALL
pc = f'{score[1]*100:.0f}'
ipc = int(pc)
if ipc == '0':
pc = c.Fore.WHITE + c.Back.GREEN + c.Style.BRIGHT + pc
elif ipc < 10:
pc = c.Fore.GREEN + c.Style.BRIGHT + pc
elif ipc <= 18:
pc = c.Fore.GREEN + pc
elif ipc <= 42:
pc = c.Fore.YELLOW + c.Style.BRIGHT + pc
elif ipc < 81:
pc = c.Fore.YELLOW + pc # looks like orange in my terminal
elif ipc < 90:
pc = c.Fore.RED + c.Style.BRIGHT + pc # dark orange --lannocc
else:
pc = c.Fore.RED + pc
pc += c.Style.RESET_ALL
return f'{fc}/{pc}'
def __str__(self):
s1 = Counter._score_(self.score1())
s5 = Counter._score_(self.score5())
s15 = Counter._score_(self.score15())
return f'{s1} {s5} {s15}'
def __add__(self, other):
result = Counter()
result.score = sorted(self.score + other.score)
return result
DEBUG_EVENTS = {
pygame_gui.UI_BUTTON_PRESSED: 'UI_BUTTON_PRESSED',
pygame_gui.UI_BUTTON_START_PRESS: 'UI_BUTTON_START_PRESS',
pygame_gui.UI_BUTTON_DOUBLE_CLICKED: 'UI_BUTTON_DOUBLE_CLICKED',
pygame_gui.UI_BUTTON_ON_HOVERED: 'UI_BUTTON_ON_HOVERED',
pygame_gui.UI_BUTTON_ON_UNHOVERED: 'UI_BUTTON_ON_UNHOVERED',
pygame_gui.UI_TEXT_ENTRY_CHANGED: 'UI_TEXT_ENTRY_CHANGED',
pygame_gui.UI_TEXT_ENTRY_FINISHED: 'UI_TEXT_ENTRY_FINISHED',
pygame_gui.UI_HORIZONTAL_SLIDER_MOVED: 'UI_HORIZONTAL_SLIDER_MOVED',
}
def debug_event(event):
if event.type in DEBUG_EVENTS:
print(f'^{DEBUG_EVENTS[event.type]}')
diff --git a/switch.py b/switch.py
--- a/switch.py
+++ b/switch.py
@@ -1,136 +1,134 @@
#!/usr/bin/env python
'''
switch.py - Optional utility for starting with DIP switches set.
'''
X = 111
Y = 199
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = f'{X},{Y}' # before pygame import
import pygame
import time
import subprocess
WIDTH = 123
HEIGHT = 456
SIZE = 27
WAIT = 0.1
BACK = (255, 255, 255)
TEXT = ( 0, 0, 0)
ROLL = (211, 255, 222)
PUSH = (123, 222, 99)
pygame.init()
pygame.display.set_caption('DIP Switch')
screen = pygame.display.set_mode((WIDTH, HEIGHT))
font = pygame.font.SysFont(pygame.font.get_default_font(), SIZE)
dip = pygame.Surface((WIDTH - SIZE, HEIGHT / 10))
dips = ''
mouse = None
keys = [ ]
run = False
while run is not None:
screen.fill(BACK)
for i in range(10):
dip.fill(PUSH if chr(i + ord('0')) in dips else ROLL)
screen.blit(dip, (SIZE, i * HEIGHT / 10))
text = font.render(str(i), True, TEXT)
screen.blit(text, (0, i * HEIGHT / 10))
pygame.display.update()
if run:
cmd = ['./start.py', dips]
print('# '+' '.join(cmd))
os.environ['SDL_VIDEO_WINDOW_POS'] = f'{X+SIZE*2},{Y-WIDTH}'
subprocess.run(cmd)
pygame.event.clear()
mouse = None
run = False
print('--- switch ready ---')
continue
time.sleep(WAIT)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = None
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_BREAK:
dips = ''
keys = [ ]
elif event.key == pygame.K_ESCAPE:
if keys:
keys = [ ]
else:
run = None
elif event.key == pygame.K_RETURN or event.key == pygame.K_KP_ENTER:
run = True
elif event.unicode >= '0' and event.unicode <= '9':
keys.append(event.key)
if event.unicode not in dips:
dips += event.unicode
else:
dips = dips.replace(event.unicode, '')
elif event.type == pygame.KEYUP:
if event.key in keys:
del keys[keys.index(event.key)]
if not keys:
run = True
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse = int(event.pos[1] / HEIGHT * 10) + ord('0')
if event.button == pygame.BUTTON_LEFT:
if chr(mouse) not in dips:
dips += chr(mouse)
elif event.button == pygame.BUTTON_RIGHT:
if chr(mouse) in dips:
dips = dips.replace(chr(mouse), '')
mouse *= -1
else:
mouse = None
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == pygame.BUTTON_LEFT \
or event.button == pygame.BUTTON_RIGHT:
mouse = None
else:
run = True
elif event.type == pygame.MOUSEMOTION:
if mouse:
mouse = int(event.pos[1] / HEIGHT * 10) + ord('0')
if not mouse < 0:
if chr(mouse) not in dips:
dips += chr(mouse)
else:
if chr(mouse) in dips:
dips = dips.replace(chr(mouse), '')
mouse *= -1
-pygame.quit()
-
diff --git a/version.py b/version.py
--- a/version.py
+++ b/version.py
@@ -1,8 +1,8 @@
-VVHEN="5.31 opeth 17+00/2"
+VVHEN="5.31 opeth 22+29/2"
THEY="yahoo.com"
SAW="LANNOCC"
ME="shawn"
print(VVHEN+' --'+SAW)
'''can you help?'''

File Metadata

Mime Type
text/x-diff
Expires
Mon, Sep 14, 6:58 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3601
Default Alt Text
(45 KB)

Event Timeline