snakeware

Python-based Linux distro for x86-64 and RPi
git clone git://squid-tech.com/snakeware.git
Log | Files | Refs | README

commit 5097db78f0638469ae79a9e74b292f8a0e752f73
parent e9854314aefda512e61f49ce294b9c7907e985b8
Author: Josh Moore <jxm5210@g.rit.edu>
Date:   Tue,  9 Jun 2020 17:15:10 -0400

Merge pull request #101 from joshiemoore/snake-bg

SnakeBG - interactive dynamic desktop backgrounds
Diffstat:
Msnakewm/README.md | 1+
Asnakewm/snakebg/__init__.py | 0
Asnakewm/snakebg/backgrounds/__init__.py | 0
Asnakewm/snakebg/backgrounds/cyber.py | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asnakewm/snakebg/backgrounds/fade.py | 38++++++++++++++++++++++++++++++++++++++
Asnakewm/snakebg/bg.py | 27+++++++++++++++++++++++++++
Asnakewm/snakebg/bgmenu.py | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Msnakewm/wm.py | 34++++++++++++++++++++++++++++++++--
8 files changed, 271 insertions(+), 2 deletions(-)

diff --git a/snakewm/README.md b/snakewm/README.md @@ -4,6 +4,7 @@ snakewm is a basic window manager built using the pygame and pygame-gui packages **Keyboard-mappings:** + Open/close App Menu: `SUPER` + Exit snakewm: `ALT+ESC` ++ Toggle dynamic backgrounds: `ALT+D` + snakepaint mappings + Toggle paint mode `ALT+P` + Change brush size `SCROLL` diff --git a/snakewm/snakebg/__init__.py b/snakewm/snakebg/__init__.py diff --git a/snakewm/snakebg/backgrounds/__init__.py b/snakewm/snakebg/backgrounds/__init__.py diff --git a/snakewm/snakebg/backgrounds/cyber.py b/snakewm/snakebg/backgrounds/cyber.py @@ -0,0 +1,120 @@ +""" +Cyberpunk/synthwave-style dynamic background for SnakeBG + +Joshua Moore 2020 +""" + +import math +import random +import pygame + +# horizontal line offsets for "scrolling effect" +CYBER_OFFS = 0 + +# list of tuples containing star information +# (x, y, radius) +CYBER_STARS = None + +# horizontal position of the ship +CYBER_SHIP_X = 200 + + +def drawbg(surface): + global CYBER_OFFS + global CYBER_STARS + global CYBER_SHIP_X + + SURF_WIDTH = surface.get_width() + SURF_HEIGHT = surface.get_height() + + # generate stars if needed + if CYBER_STARS is None: + CYBER_STARS = [] + for x in range(50, 100): + CYBER_STARS.append( + ( + random.randint(0, SURF_WIDTH), + random.randint(0, SURF_HEIGHT / 2 - 5), + random.randint(1, 4), + ) + ) + + surface.fill((0, 0, 0)) + + # draw horizon line + pygame.draw.line( + surface, (255, 0, 255), (0, SURF_HEIGHT / 2), (SURF_WIDTH, SURF_HEIGHT / 2) + ) + + # draw vertical lines + for theta in range(0, 180, 6): + tdeg = math.radians(theta) + pygame.draw.line( + surface, + (255, 0, 255), + (SURF_WIDTH / 2, SURF_HEIGHT / 2), + ( + SURF_WIDTH / 2 + math.cos(tdeg) * 2000, + SURF_HEIGHT / 2 + math.sin(tdeg) * 2000, + ), + ) + + # draw horizontal lines + y = (SURF_HEIGHT / 2) - 20 + dy = 1 + while y <= SURF_HEIGHT: + ty = y + CYBER_OFFS * (dy / 10) + if ty > SURF_HEIGHT / 2: + pygame.draw.line(surface, (255, 0, 255), (0, ty), (SURF_WIDTH, ty)) + + y = y + dy + dy = dy + 5 + + CYBER_OFFS = CYBER_OFFS + 0.1 + if CYBER_OFFS > 10: + CYBER_OFFS = 0 + + # draw ship + draw_ship( + surface, (int(SURF_WIDTH / 2), int(SURF_HEIGHT / 2)), CYBER_SHIP_X / SURF_WIDTH + ) + + CYBER_SHIP_X = CYBER_SHIP_X - int((CYBER_SHIP_X - pygame.mouse.get_pos()[0]) / 50) + + # draw stars + for star in CYBER_STARS: + pygame.draw.circle(surface, (0, 255, 255), (star[0], star[1]), star[2]) + + # draw sun + pygame.draw.arc( + surface, + (255, 0, 255), + pygame.Rect(SURF_WIDTH / 2 - 150, SURF_HEIGHT / 2 - 150, 300, 300), + 0, + math.radians(181), + 2, + ) + + +def draw_ship(surface, origin, dx): + """ + Draw the "space ship" + origin - tuple representing center of the screen + dx - (shipX / screen_width) + """ + fx = ( + origin[0] - int(math.cos(math.radians(dx * 180)) * 700), + origin[1] + int(math.sin(math.radians(dx * 180)) * 300), + ) + + fl = ( + origin[0] - int(math.cos(math.radians((dx - 0.05) * 180)) * 700), + origin[1] + int(math.sin(math.radians((dx - 0.1) * 180)) * 500), + ) + + fr = ( + origin[0] - int(math.cos(math.radians((dx + 0.05) * 180)) * 700), + origin[1] + int(math.sin(math.radians((dx + 0.1) * 180)) * 500), + ) + + pygame.draw.polygon(surface, (0, 255, 255), (fx, fl, fr), 12) diff --git a/snakewm/snakebg/backgrounds/fade.py b/snakewm/snakebg/backgrounds/fade.py @@ -0,0 +1,38 @@ +""" +Fading color background for SnakeBG + +Joshua Moore 2020 +""" + +FCOLOR_R = 0 +FCOLOR_G = 0 +FCOLOR_B = 0 +FCOLOR_STEP = 1 + + +def drawbg(surface): + global FCOLOR_R + global FCOLOR_G + global FCOLOR_B + global FCOLOR_STEP + + surface.fill((FCOLOR_R, FCOLOR_G, FCOLOR_B)) + + if FCOLOR_STEP > 0: + if FCOLOR_R < 255: + FCOLOR_R = FCOLOR_R + FCOLOR_STEP + elif FCOLOR_G < 255: + FCOLOR_G = FCOLOR_G + FCOLOR_STEP + elif FCOLOR_B < 255: + FCOLOR_B = FCOLOR_B + FCOLOR_STEP + else: + FCOLOR_STEP = -FCOLOR_STEP + elif FCOLOR_STEP < 0: + if FCOLOR_R > 0: + FCOLOR_R = FCOLOR_R + FCOLOR_STEP + elif FCOLOR_G > 0: + FCOLOR_G = FCOLOR_G + FCOLOR_STEP + elif FCOLOR_B > 0: + FCOLOR_B = FCOLOR_B + FCOLOR_STEP + else: + FCOLOR_STEP = -FCOLOR_STEP diff --git a/snakewm/snakebg/bg.py b/snakewm/snakebg/bg.py @@ -0,0 +1,27 @@ +""" +SnakeBG - dynamic backgrounds for SnakeWM! + +Joshua Moore 2020 +""" + +import importlib + + +class SnakeBG: + # reference to the imported background + _BG = None + + def __init__(self, bgname, testmode): + bgmod = "snakebg.backgrounds." + bgname + if not testmode: + bgmod = "snakewm." + bgmod + + # actually import the background + self._BG = importlib.import_module(bgmod) + + def draw(self, surface): + # draw the background if the _BG module is set + if self._BG is None: + return + + self._BG.drawbg(surface) diff --git a/snakewm/snakebg/bgmenu.py b/snakewm/snakebg/bgmenu.py @@ -0,0 +1,53 @@ +""" +Background picker menu for SnakeBG + +Joshua Moore 2020 +""" + +import os + +import pygame +import pygame_gui + +from pygame_gui.elements import UIWindow +from pygame_gui.elements import UIButton + + +class SnakeBGMenu(UIWindow): + # size of each menu button + BSIZE = (200, 20) + + # list of background modules + BGLIST = None + + def __init__(self, manager): + # load bg module names + bgdir = os.path.dirname(os.path.abspath(__file__)) + "/backgrounds/" + self.BGLIST = [] + for f in os.listdir(bgdir): + if "__" in f: + continue + self.BGLIST.append(f[:-3]) + self.BGLIST = sorted(self.BGLIST) + + # create window + super().__init__( + pygame.Rect( + (100, 100), (self.BSIZE[0] + 32, self.BSIZE[1] * len(self.BGLIST)) + ), + manager=manager, + window_display_title="SnakeBG", + object_id="#bgmenu", + resizable=False, + ) + + # add buttons + for i in range(len(self.BGLIST)): + UIButton( + relative_rect=pygame.Rect((0, self.BSIZE[1] * i), self.BSIZE), + text=self.BGLIST[i], + manager=manager, + container=self, + parent_element=self, + object_id=self.BGLIST[i], + ) diff --git a/snakewm/wm.py b/snakewm/wm.py @@ -12,9 +12,15 @@ import pygame, pygame_gui if TESTMODE: from appmenu.appmenupanel import AppMenuPanel + + from snakebg.bg import SnakeBG + from snakebg.bgmenu import SnakeBGMenu else: from snakewm.appmenu.appmenupanel import AppMenuPanel + from snakewm.snakebg.bg import SnakeBG + from snakewm.snakebg.bgmenu import SnakeBGMenu + class SnakeWM: SCREEN = None @@ -53,6 +59,9 @@ class SnakeWM: PAINT_SHAPE = 0 NUM_SHAPES = 3 + # reference to SnakeBG object for dynamic backgrounds + DYNBG = None + # currently focused window FOCUS = None @@ -183,6 +192,13 @@ class SnakeWM: # toggle paint mode self.PAINT = not self.PAINT self.BRUSH_SURF.fill((0, 0, 0, 0)) + elif event.key == pygame.K_d: + # toggle dynamic background + if self.DYNBG is None: + SnakeBGMenu(self.MANAGER) + else: + del self.DYNBG + self.DYNBG = None elif event.type == pygame.MOUSEBUTTONDOWN: if self.PAINT: @@ -226,13 +242,27 @@ class SnakeWM: elif event.user_type == pygame_gui.UI_FILE_DIALOG_PATH_PICKED: if event.ui_object_id == "#background_picker": self.set_bg_image(event.text) + elif event.user_type == pygame_gui.UI_BUTTON_PRESSED: + if ( + "#bgmenu" in event.ui_object_id + and not "title_bar" in event.ui_object_id + and not "close_button" in event.ui_object_id + ): + selected_bg = event.ui_object_id.split(".")[1] + self.DYNBG = SnakeBG(selected_bg, TESTMODE) + self.PAINT = False self.MANAGER.process_events(event) self.MANAGER.update(delta) - # blit paintbrush layer - if self.PAINT: + # blit paintbrush/dynbg layer + if self.DYNBG is not None: + # update dynamic background + self.DYNBG.draw(self.BRUSH_SURF) + self.SCREEN.blit(self.BG, (0, 0)) + self.SCREEN.blit(self.BRUSH_SURF, (0, 0)) + elif self.PAINT: mpos = pygame.mouse.get_pos() # default drawing the brush to the temporary brush layer