Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4357
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
45 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Sep 14, 6:58 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3601
Default Alt Text
(45 KB)
Attached To
Mode
rK Media System
Attached
Detach File
Event Timeline
Log In to Comment