diff --git a/.gitignore b/.gitignore index 3e20d37..e812c3b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ sys.py/.lang !**/Jobs/.gitkeep !**/Jobs/00_lowpower.sh !**/Jobs/00_lowpower.alias - +.done diff --git a/Menu/GameShell/50_PICO-8/PICO-8.sh b/Menu/GameShell/50_PICO-8/PICO-8.sh new file mode 100755 index 0000000..cfbba82 --- /dev/null +++ b/Menu/GameShell/50_PICO-8/PICO-8.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +#SDL_VIDEODRIVER=x11 DISPLAY=:0 ./pico-8/pico8_dyn -splore -draw_rect 32,0,256,240 +cd /home/cpi/games/PICO-8/pico-8 +SDL_VIDEODRIVER=x11 DISPLAY=:0 ./pico8_dyn -draw_rect 32,0,256,240 diff --git a/Menu/GameShell/50_PICO-8/Post-Up.sh b/Menu/GameShell/50_PICO-8/Post-Up.sh new file mode 100755 index 0000000..f2062a3 --- /dev/null +++ b/Menu/GameShell/50_PICO-8/Post-Up.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +mkdir ~/.lexaloffle + +cp -rf pico-8 ~/.lexaloffle + +touch .done + diff --git a/Menu/GameShell/50_PICO-8/__init__.py b/Menu/GameShell/50_PICO-8/__init__.py deleted file mode 100644 index 5c0b610..0000000 --- a/Menu/GameShell/50_PICO-8/__init__.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- coding: utf-8 -*- -import pygame -import validators - -from UI.constants import Width,Height,ICON_TYPES,RUNEVT -#from UI.simple_name_space import SimpleNamespace -from UI.page import Page -from UI.label import Label -from UI.fonts import fonts -from UI.icon_item import IconItem -from UI.icon_pool import MyIconPool -from UI.keys_def import CurKeys -from UI.skin_manager import MySkinManager -from UI.lang_manager import MyLangManager -from UI.text_bulletinboard import Textbulletinboard,Text -from UI.util_funcs import FileExists - - -class NOPICOPage(Page): - _FootMsg = ["Nav","","","Back",""] - - def Init(self): - self._PosX = self._Index*self._Screen._Width - self._Width = self._Screen._Width - self._Height = self._Screen._Height - - self._CanvasHWND = self._Screen._CanvasHWND - - self._Board = Textbulletinboard() - - self._Board._PosX = 4 - self._Board._PosY = 20 - self._Board._Width= self._Width - 4*2 - self._Board._Height = 100 - self._Board._CanvasHWND = self._CanvasHWND - self._Board.Init() - - a = Text("Please Go to \n",None,MyLangManager.TrFont("varela14"),True) - b = Text("https://www.lexaloffle.com/pico-8.php",MySkinManager.GiveColor("URL"),None,True,True) - c = Text("buy a pico-8 raspi and put zip into \n/home/cpi/games/PICO-8") - - d = a.Words()+b.Words()+c.Words() - self._Board.SetAndBlitText(d) - - def KeyDown(self,event): - if event.key == CurKeys["A"] or event.key == CurKeys["Menu"]: - self.ReturnToUpLevelPage() - self._Screen.Draw() - self._Screen.SwapAndShow() - return - - def Draw(self): - self.ClearCanvas() - self._Board.Draw() - - -class PICO8ZipHashErrPage(Page): - _FootMsg = ["Nav","","","Cancel","Continue"] - - def Init(self): - self._PosX = self._Index*self._Screen._Width - self._Width = self._Screen._Width - self._Height = self._Screen._Height - - self._CanvasHWND = self._Screen._CanvasHWND - - self._Board = Textbulletinboard() - - self._Board._PosX = 4 - self._Board._PosY = self._Height/2 - 35 - self._Board._Width= self._Width - 4*2 - self._Board._Height = 100 - self._Board._CanvasHWND = self._CanvasHWND - self._Board._Align = "Center" - self._Board.Init() - - a = Text("Md5sum check error\n",None,MyLangManager.TrFont("varela24")) - b = Text("continue anyway?\n",None,MyLangManager.TrFont("varela24")) - - self._Board.SetAndBlitText(a.Words()+b.Words()) - - def KeyDown(self,event): - if event.key == CurKeys["A"] or event.key == CurKeys["Menu"]: - self.ReturnToUpLevelPage() - self._Screen.Draw() - self._Screen.SwapAndShow() - return - - def Draw(self): - self.ClearCanvas() - self._Board.Draw() - - -class APIOBJ(object): - - _Page = None - _pico8 ="/home/cpi/games/PICO-8/pico-8" - - def __init__(self): - pass - - def CheckPico8(self): - if FileExists(self._pico8): - return True - - def Init(self,main_screen): - self._NOPicoPage = NOPICOPage() - self._NOPicoPage._Name = "Not Found" - self._NOPicoPage._Screen = main_screen - self._NOPicoPage.Init() - - self._HashErrPage = PICO8ZipHashErrPage() - self._HashErrPage._Name = "Md5sum check failed" - self._HashErrPage._Screen = main_screen - self._HashErrPage.Init() - - def API(self,main_screen): - if main_screen !=None: - if self.CheckPico8() == False: - main_screen._MsgBox.SetText("Starting pico-8") - main_screen._MsgBox.Draw() - main_screen.SwapAndShow() - pygame.time.delay(300) - cmdpath = "/home/cpi/games/PICO-8/PICO-8.sh" - pygame.event.post( pygame.event.Event(RUNEVT, message=cmdpath)) - else: - main_screen.PushPage(self._NOPicoPage) - #main_screen.PushPage(self._HashErrPage) - main_screen.Draw() - main_screen.SwapAndShow() - -OBJ = APIOBJ() -def Init(main_screen): - OBJ.Init(main_screen) -def API(main_screen): - OBJ.API(main_screen) diff --git a/Menu/GameShell/50_PICO-8/compkginfo.json b/Menu/GameShell/50_PICO-8/compkginfo.json new file mode 100644 index 0000000..77a86cc --- /dev/null +++ b/Menu/GameShell/50_PICO-8/compkginfo.json @@ -0,0 +1,9 @@ +{ +"GameDir":"/home/cpi/games/PICO-8/", +"InstallDir":"pico-8", +"NotFoundMsg":["Please purchase the PICO-8 \n|None|varela16", +"and copy it to the \"Games\" folder|None|varela16"], + +"MD5":{"pico-8_0.1.11g_raspi.zip":"a3f2995cf117499f880bd964d6a0e1f2","pico-8_0.1.11g_amd64.zip":"6726141c784afd4a41be6b7414c1b932"}, +"Post-Up":"bash Post-Up.sh" +} diff --git a/Menu/GameShell/50_PICO-8/md5sum.log b/Menu/GameShell/50_PICO-8/md5sum.log deleted file mode 100644 index f66e2de..0000000 --- a/Menu/GameShell/50_PICO-8/md5sum.log +++ /dev/null @@ -1,2 +0,0 @@ -a3f2995cf117499f880bd964d6a0e1f2 pico-8_0.1.11g_raspi.zip -6726141c784afd4a41be6b7414c1b932 pico-8_0.1.11g_amd64.zip diff --git a/Menu/GameShell/50_PICO-8/pico-8/config.txt b/Menu/GameShell/50_PICO-8/pico-8/config.txt new file mode 100644 index 0000000..15ea6fc --- /dev/null +++ b/Menu/GameShell/50_PICO-8/pico-8/config.txt @@ -0,0 +1,99 @@ +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Configuration for pico-8 +// +// config.txt is read on startup and saved on exit. +// To generate the default config.txt, delete this file. +// +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +// :: Video Settings + +window_size 0 0 // window width, height +screen_size 0 0 // screen width, height (stretched to window) +show_fps 0 // Draw frames per second in the corner + + +// :: Window Settings + +windowed 0 // 1 to start up in windowed mode +window_position -1 -1 // x and y position of window, or -1, -1 to let the window manager decide +frameless 0 // 1 to use a window with no frame +fullscreen_method 1 // 0 maximized window (linux) 1 borderless desktop-sized window 2 fullscreen + + +// :: System Settings + +foreground_sleep_ms 1 // number of milliseconds to sleep each frame. Try 10 to conserve battery power + +background_sleep_ms 20 // number of milliseconds to sleep each frame when running in the background + +sessions 4 // number of times program has been run + +// (scancode) hold this key down and left-click to simulate right-click +rmb_key 0 // 0 for none 226 for LALT + +// 0:off 1: ignore SDL_TEXTINPUT and use SDL_GetKeyboardState instead (mapped to a US layout) +emulate_textinput 1 + +// Desktop for saving screenshots etc. Defaults to $HOME/Desktop +desktop_path + + + +// :: Audio Settings + +sound_volume 256 // 0..256 +music_volume 256 // 0..256 +mix_buffer_size 1024 // usually 1024. Try 2048 if you get choppy sound + + +// :: + +version 0.1.11g + + +// Location of pico-8's root folder +root_path /home/cpi/.lexaloffle/pico-8/carts/ + + +// Location of cartridge save data +cdata_path /home/cpi/.lexaloffle/pico-8/cdata/ + + +// Specify which player index joystick control begins at (0..7) +joystick_index 0 + + +// Custom keyboard scancodes for buttons. player0 0..6, player1 0..5 +button_keys 0 0 0 0 13 14 0 0 0 0 0 0 0 + +// Play notes as they are plotted in frequency mode +live_notes 0 + +// iff 1: when using keyboard cursor, snap to closest pixel / map cel +cursor_snap 0 + +// maximum length of gif in seconds (1..120, default 8) +gif_len 8 + +// 0 classic 1 dark blue background in code editor +gui_theme 0 + +// scale of screenshots and gifs // 2 means 256x256 +screenshot_scale 3 +gif_scale 2 + +// when 1 can enter glyphs using shift-A..Z +shift_glyphs 1 + +// 0 for off. 1 to notify whenever unsaved changes are backed up +show_backup_messages 1 + +// 0 for off. 1 to allow control of a cart's framerate due to host machine's cpu capacity (recommended) +host_framerate_control 1 + +// filter splore content +// 0 for no filter (18+) 1 medium (13+) 2 maximum (kid-friendly) +content_filter 1 + diff --git a/Menu/GameShell/50_PICO-8/pico-8/log.txt b/Menu/GameShell/50_PICO-8/pico-8/log.txt new file mode 100644 index 0000000..3f783a2 --- /dev/null +++ b/Menu/GameShell/50_PICO-8/pico-8/log.txt @@ -0,0 +1,90 @@ +codo_init + platform: Linux + Found config.txt + + 01 window_size 0 0 // window width, height + 02 screen_size 0 0 // screen width, height (stretched to window) + 03 show_fps 0 // Draw frames per second in the corner + 04 windowed 0 // 1 to start up in windowed mode + 05 window_position -1 -1 // x and y position of window, or -1, -1 to let the window manager decide + new window position: -1, -1 + 06 frameless 0 // 1 to use a window with no frame + 07 fullscreen_method 1 // 0 maximized window (linux) 1 borderless desktop-sized window 2 fullscreen + 08 foreground_sleep_ms 1 // number of milliseconds to sleep each frame. Try 10 to conserve battery power + 09 background_sleep_ms 20 // number of milliseconds to sleep each frame when running in the background + 10 sessions 3 // number of times program has been run + 11 rmb_key 0 // 0 for none 226 for LALT + 12 emulate_textinput 1 + 13 desktop_path + 14 sound_volume 256 // 0..256 + 15 music_volume 256 // 0..256 + 16 mix_buffer_size 1024 // usually 1024. Try 2048 if you get choppy sound + 17 version 0.1.11g + 18 root_path /home/cpi/.lexaloffle/pico-8/carts/ + 19 cdata_path /home/cpi/.lexaloffle/pico-8/cdata/ + 20 joystick_index 0 + 21 button_keys 0 0 0 0 0 0 0 0 0 0 0 0 0 + 22 live_notes 0 + 23 cursor_snap 0 + 24 gif_len 8 + 25 gui_theme 0 + 26 screenshot_scale 3 + 27 gif_scale 2 + 28 shift_glyphs 1 + 29 show_backup_messages 1 + 30 host_framerate_control 1 + 31 content_filter 1 + + codo_system_init + Compiled against SDL version: 2.0.7 + Linked against SDL version: 2.0.5 + Built-in video drivers: 0 x11 1 wayland 2 dummy + Current video driver: x11 + Built-in render drivers: + Renderer opengl: + Flags: 0x0000000E ( | | ) + Texture formats (1): ARGB8888 + Renderer opengles2: + Flags: 0x0000000E ( | | ) + Texture formats (4): ARGB8888, ABGR8888, RGB888, BGR888 + Renderer software: + Flags: 0x00000009 ( | ) + Texture formats (8): ARGB8888, ABGR8888, RGBA8888, BGRA8888, RGB888, BGR888, RGB565, RGB555 + codo_reset_timer + codo_gui_init + codo_keys_init + codo_text_init + codo_video_init + codo_mouse_init + codo_joystick_init + Reading controller mappings: /home/cpi/.lexaloffle/pico-8/sdl_controllers.txt + searching for joysticks + found 0 joysticks + ok +ok +codo_load_pod: /home/cpi/apps/Menu/50_PICO-8/pico8.dat ok +codo_set_screen 128 128 8 100 + set pixel_perfect 1 + window size: 640 480 +codo_plat_pi: forcing fullscreen mode +Current renderer: + Renderer opengl: + Flags: 0x0000000A ( | ) + Texture formats (5): ARGB8888, YV12, IYUV, 0x3231564e, 0x3132564e + Max Texture Size: 8192x8192 +codo_sound_init mix_buffer_size: 1024 +codo_sound_init +SDL_INIT_AUDIO ok +SDL_OpenAudio ok +Built-in audio drivers: 0 pulseaudio 1 alsa 2 sndio 3 dsp 4 disk 5 dummy +Current audio driver: alsa +codo_exit + cmusic_stop + codo_main_exit + codo_config_save + codo_sound_exit + codo_video_exit + codo_joystick_exit + codo_system_exit + codo_items_created: 1023 +ok diff --git a/Menu/GameShell/50_PICO-8/pico-8/sdl_controllers.txt b/Menu/GameShell/50_PICO-8/pico-8/sdl_controllers.txt new file mode 100644 index 0000000..d6719d7 --- /dev/null +++ b/Menu/GameShell/50_PICO-8/pico-8/sdl_controllers.txt @@ -0,0 +1 @@ +// add SDL2 game controller mappings to this file diff --git a/skin/default/Menu/GameShell/PICO-8.png b/skin/default/Menu/GameShell/PICO-8.png index 65ef00b..26b80d2 100644 Binary files a/skin/default/Menu/GameShell/PICO-8.png and b/skin/default/Menu/GameShell/PICO-8.png differ diff --git a/skin/default/sys.py/gameshell/icons/pico8_md5_err.png b/skin/default/sys.py/gameshell/icons/pico8_md5_err.png new file mode 100644 index 0000000..8b281a1 Binary files /dev/null and b/skin/default/sys.py/gameshell/icons/pico8_md5_err.png differ diff --git a/skin/default/sys.py/gameshell/icons/pico8_notfound.png b/skin/default/sys.py/gameshell/icons/pico8_notfound.png new file mode 100644 index 0000000..f4f39af Binary files /dev/null and b/skin/default/sys.py/gameshell/icons/pico8_notfound.png differ diff --git a/sys.py/UI/CommercialSoftwarePackage/__init__.py b/sys.py/UI/CommercialSoftwarePackage/__init__.py new file mode 100644 index 0000000..ba5b066 --- /dev/null +++ b/sys.py/UI/CommercialSoftwarePackage/__init__.py @@ -0,0 +1,342 @@ +# -*- coding: utf-8 -*- + +""" +Package /home/cpi/games/xxx/yyy.zip ,only support in zip + +com_pkg_info /home/cpi/launcher/Menu/GameShell/xxxx/compkginfo.json +use https://jsonlint.com/ to validate first in case syntax err + +``` +{ +"NotFoundMsg":["Please Go to \n|None|varela14|True", +"https://www.lexaloffle.com/pico-8.php|URL|None|True|True", +"buy a pico-8 raspi and put zip into \n/home/cpi/games/PICO-8"] + +"MD5":{"pico-8_0.1.11g_raspi.zip":"a3f2995cf117499f880bd964d6a0e1f2","pico-8_0.1.11g_amd64.zip":"6726141c784afd4a41be6b7414c1b932"} +} + +``` + +""" + +import pygame +#import validators +import os +import commands +from UI.constants import Width,Height,ICON_TYPES,RUNEVT,RESTARTUI +#from UI.simple_name_space import SimpleNamespace +from UI.page import Page +from UI.label import Label +from UI.fonts import fonts +from UI.icon_item import IconItem +from UI.icon_pool import MyIconPool +from UI.keys_def import CurKeys +from UI.skin_manager import MySkinManager +from UI.lang_manager import MyLangManager +from UI.text_bulletinboard import Textbulletinboard,Text +from UI.util_funcs import FileExists + + +class NotFoundPage(Page): + _FootMsg = ["Nav","","","Back",""] + _BG = "pico8_notfound" + _Leader = None + _Padding = pygame.Rect(0,20,0,0) + def Init(self): + self._PosX = self._Index*self._Screen._Width + self._Width = self._Screen._Width + self._Height = self._Screen._Height + + self._CanvasHWND = self._Screen._CanvasHWND + + self._BGpng = IconItem() + self._BGpng._ImgSurf = MyIconPool._Icons[self._BG] + self._BGpng._MyType = ICON_TYPES["STAT"] + self._BGpng._Parent = self + #print( MyIconPool.Width(self._BG),MyIconPool.Height(self._BG) ) + self._BGpng.Adjust(0,0,MyIconPool.Width(self._BG),MyIconPool.Height(self._BG),0) + + self._Board = Textbulletinboard() + + self._Board._PosX = 4 + self._Board._PosY = 100 + self._Board._Width= self._Width - 4*2 + self._Board._Height = 100 + self._Board._CanvasHWND = self._CanvasHWND + self._Board._Align = "Center" + self._Board._RowPitch =30 + self._Board.Init() + + if self._Leader!= None and self._Leader._ComPkgInfo != None: + if "NotFoundMsg" in self._Leader._ComPkgInfo: + d = [] + for i, v in enumerate(self._Leader._ComPkgInfo["NotFoundMsg"]): + Color = None + Font = None + Bold = False + Und = False + Txt = "" + parts = v.split("|") + if len(parts) > 0: + Txt = parts[0] + + if len(parts) == 2: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + elif len(parts) == 3: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + if parts[2] != "None": + Font = MyLangManager.TrFont(parts[2]) + elif len(parts) == 4: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + if parts[2] != "None": + Font = MyLangManager.TrFont(parts[2]) + if parts[3] == "True": + Bold = True + elif len(parts) == 5: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + if parts[2] != "None": + Font = MyLangManager.TrFont(parts[2]) + if parts[3] == "True": + Bold = True + if parts[4] == "True": + Und = True + + a = Text(Txt,Color,Font,Bold,Und) + d = d + a.Words() + + self._Board.SetAndBlitText(d) + + def KeyDown(self,event): + if event.key == CurKeys["A"] or event.key == CurKeys["Menu"]: + self.ReturnToUpLevelPage() + self._Screen.Draw() + self._Screen.SwapAndShow() + return + + def Draw(self): + self.ClearCanvas() + if self._BGpng != None: + self._BGpng.NewCoord((self._Width-self._BGpng._Width)/2,self._Padding.y ) + self._BGpng.DrawTopLeft() + self._Board._PosY = self._BGpng._Height+self._Padding.y + else: + self._Board._PosY = self._Padding.y + + self._Board.Draw() + + +class HashErrPage(Page): + _FootMsg = ["Nav","","","Cancel","Continue"] + _BG ="pico8_md5_err" + + _Leader = None + _Padding = pygame.Rect(0,20,0,0) + + def Init(self): + self._PosX = self._Index*self._Screen._Width + self._Width = self._Screen._Width + self._Height = self._Screen._Height + + self._CanvasHWND = self._Screen._CanvasHWND + + self._BGpng = IconItem() + self._BGpng._ImgSurf = MyIconPool._Icons[self._BG] + self._BGpng._MyType = ICON_TYPES["STAT"] + self._BGpng._Parent = self + self._BGpng.Adjust(0,0,MyIconPool.Width(self._BG),MyIconPool.Height(self._BG),0) + + self._Board = Textbulletinboard() + + self._Board._PosX = 4 + self._Board._PosY = self._Height/2 - 35 + self._Board._Width= self._Width - 4*2 + self._Board._Height = 100 + self._Board._CanvasHWND = self._CanvasHWND + self._Board._RowPitch =30 + self._Board._Align = "Center" + self._Board.Init() + + if self._Leader!= None and self._Leader._ComPkgInfo != None: + if "HashErrMsg" in self._Leader._ComPkgInfo: + d = [] + for i, v in enumerate(self._Leader._ComPkgInfo["HashErrMsg"]): + Color = None + Font = None + Bold = False + Und = False + Txt = "" + parts = v.split("|") + if len(parts) > 0: + Txt = parts[0] + + if len(parts) == 2: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + elif len(parts) == 3: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + if parts[2] != "None": + Font = MyLangManager.TrFont(parts[2]) + elif len(parts) == 4: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + if parts[2] != "None": + Font = MyLangManager.TrFont(parts[2]) + if parts[3] == "True": + Bold = True + elif len(parts) == 5: + if parts[1] != "None": + Color = MySkinManager.GiveColor(parts[1]) + if parts[2] != "None": + Font = MyLangManager.TrFont(parts[2]) + if parts[3] == "True": + Bold = True + if parts[4] == "True": + Und = True + + a = Text(Txt,Color,Font,Bold,Und) + d = d + a.Words() + + self._Board.SetAndBlitText(d) + + else: + a = Text("MD5 check Failed!\n",None,MyLangManager.TrFont("varela16")) + b = Text("Do you want to continue?",None,MyLangManager.TrFont("varela16")) + self._Board.SetAndBlitText(a.Words()+b.Words()) + + def KeyDown(self,event): + if event.key == CurKeys["A"] or event.key == CurKeys["Menu"]: + self.ReturnToUpLevelPage() + self._Screen.Draw() + self._Screen.SwapAndShow() + return + + if event.key == CurKeys["B"]: + self._Leader.InstallPackage(self._Screen) + return + + def OnLoadCb(self): + pass + + def Draw(self): + self.ClearCanvas() + if self._BGpng != None: + self._BGpng.NewCoord((self._Width-self._BGpng._Width)/2,self._Padding.y) + self._BGpng.DrawTopLeft() + self._Board._PosY = self._BGpng._Height+self._Padding.y + else: + self._Board._PosY = self._Padding.y + + self._Board.Draw() + + +class MyCommercialSoftwarePackage(object): + _ComPkgInfo = None + _Done = "" + _InvokeDir = "" + + def __init__(self): + pass + + def InstallPackage(self,main_screen): + main_screen._MsgBox.SetText("Installing the package") + main_screen._MsgBox.Draw() + main_screen.SwapAndShow() + json_config = self._ComPkgInfo + cur_dir = os.getcwd() + + os.chdir(json_config["GameDir"]) + for i,v in enumerate(json_config["MD5"]): + os.system("unzip -o %s" %v) ## auto overwrite + + if "Post-Up" in json_config: + if FileExists(self._InvokeDir): + os.chdir(self._InvokeDir) + + os.system(json_config["Post-Up"]) + + + os.chdir(cur_dir) + pygame.time.delay(1000) + + main_screen._MsgBox.SetText("Package Installed") + main_screen._MsgBox.Draw() + main_screen.SwapAndShow() + pygame.time.delay(500) + + pygame.event.post( pygame.event.Event(RESTARTUI, message="")) + + def VerifyPackage(self,main_screen): + ## do unzip and check md5sum once + + main_screen._MsgBox.SetText("Verify the package") + main_screen._MsgBox.Draw() + main_screen.SwapAndShow() + pygame.time.delay(400) + + Checked = False + + json_config = self._ComPkgInfo + if json_config == None: + return + + if "MD5" in json_config: + for i,v in enumerate(json_config["MD5"]): + print(i,v) + if FileExists( os.path.join(json_config["GameDir"], v )): + print( os.path.join(json_config["GameDir"],v )) + out = commands.getstatusoutput("md5sum %s" % os.path.join(json_config["GameDir"],v)) + ret = out[1] + ret = ret.split(" ") + print(ret) + if ret[0] == json_config["MD5"][v]: + print("md5 is ok") + Checked = True + + return Checked + + return Checked + + def Init(self,main_screen): + self._Page1 = NotFoundPage() + self._Page1._Name = "Not Found" + self._Page1._Screen = main_screen + self._Page1._Leader = self + self._Page1.Init() + + self._Page2 = HashErrPage() + self._Page2._Name = "Md5sum check failed" + self._Page2._Screen = main_screen + self._Page2._Leader = self + self._Page2.Init() + + + def API(self,main_screen): + if main_screen !=None: + if self._Done != "": + main_screen._MsgBox.SetText("Starting") + main_screen._MsgBox.Draw() + main_screen.SwapAndShow() + pygame.time.delay(300) + #### + + pygame.event.post( pygame.event.Event(RUNEVT, message=self._Done)) + #### + else: + print(self._ComPkgInfo) + if FileExists( os.path.join(self._ComPkgInfo["GameDir"],self._ComPkgInfo["InstallDir"] )) == False: + main_screen.PushPage(self._Page1) + main_screen.Draw() + main_screen.SwapAndShow() + else: + if self.VerifyPackage(main_screen) == False: + main_screen.PushPage(self._Page2) + main_screen.Draw() + main_screen.SwapAndShow() + else: + self.InstallPackage(main_screen) + diff --git a/sys.py/UI/constants.py b/sys.py/UI/constants.py index c6b8574..6aab244 100644 --- a/sys.py/UI/constants.py +++ b/sys.py/UI/constants.py @@ -24,7 +24,7 @@ icon_height = 80 icon_ext = ".sh" -ICON_TYPES={"Emulator":7,"FILE":6,"STAT":5,"NAV":4,"LETTER":3,"FUNC":2,"DIR":1,"EXE":0,"None":-1} # FUNC is like UI widget's function,DIR contains child page,EXE just execute a binary +ICON_TYPES={"Commercial":8,"Emulator":7,"FILE":6,"STAT":5,"NAV":4,"LETTER":3,"FUNC":2,"DIR":1,"EXE":0,"None":-1} # FUNC is like UI widget's function,DIR contains child page,EXE just execute a binary ## H=horizontal ,V=vertical S=Single Line #SLeft start from left, single line diff --git a/sys.py/UI/icon_item.py b/sys.py/UI/icon_item.py index 8edea09..237f3d1 100644 --- a/sys.py/UI/icon_item.py +++ b/sys.py/UI/icon_item.py @@ -81,7 +81,26 @@ class IconItem(Widget): def Clear(self): pass + + def DrawTopLeft(self): + if self._Align==ALIGN["VCenter"]: #default + if self._Label != None: + self._Label._PosX = self._PosX - self._Label._Width/2 + self._Parent._PosX + self._Label._PosY = self._PosY + self._Height/2 +6 + self._Parent._PosY + + elif self._Align ==ALIGN["HLeft"]: + if self._Label != None: + self._Label._PosX = self._PosX + self._Width/2 + 3 + self._Parent._PosX + self._Label._PosY = self._PosY - self._Label._Height/2 + self._Parent._PosY + if self._Label!=None: + self._Label.Draw() + + if self._ImgSurf != None: + self._Parent._CanvasHWND.blit(self._ImgSurf,pygame.Rect(self._PosX+self._Parent._PosX, + self._PosY+self._Parent._PosY, + self._Width, + self._Height)) def Draw(self): if self._Align==ALIGN["VCenter"]: #default if self._Label != None: diff --git a/sys.py/UI/icon_pool.py b/sys.py/UI/icon_pool.py index f08058c..dc04b1c 100644 --- a/sys.py/UI/icon_pool.py +++ b/sys.py/UI/icon_pool.py @@ -13,6 +13,7 @@ class IconPool(object): _GameShellIconPath = SkinMap("gameshell/icons/") _Icons = {} + _Sizes = {} def __init__(self): self._Icons= {} @@ -23,7 +24,24 @@ class IconPool(object): if os.path.isfile(self._GameShellIconPath+"/"+i) and i.endswith(".png"): keyname = i.split(".")[0] self._Icons[keyname] = pygame.image.load(self._GameShellIconPath+"/"+i).convert_alpha() - + self._Sizes[keyname] = self._Icons[keyname].get_size() + + def Width(self,keyname): + if keyname in self._Sizes: + return self._Sizes[keyname][0] + + def Height(self,keyname): + if keyname in self._Sizes: + return self._Sizes[keyname][1] + +##global Handler +MyIconPool = None + +def InitMyIconPool(): + global MyIconPool + if MyIconPool == None: + MyIconPool = IconPool() + +InitMyIconPool() -MyIconPool = IconPool() diff --git a/sys.py/UI/lang_manager.py b/sys.py/UI/lang_manager.py index 0a1de09..5a027e7 100644 --- a/sys.py/UI/lang_manager.py +++ b/sys.py/UI/lang_manager.py @@ -89,7 +89,10 @@ class LangManager(object): return english_key_str def TrFont(self,orig_font_str): - font_size_number = int(filter(str.isdigit, orig_font_str)) + try: + font_size_number = int(filter(str.isdigit, orig_font_str)) + except TypeError: + font_size_number = int(filter(unicode.isdigit, orig_font_str)) if font_size_number > 120: raise Exception('font string format error') diff --git a/sys.py/UI/main_screen.py b/sys.py/UI/main_screen.py index 3a12a0e..f390b8d 100644 --- a/sys.py/UI/main_screen.py +++ b/sys.py/UI/main_screen.py @@ -5,7 +5,7 @@ from pygame.locals import * from sys import exit import os import sys - +import json from operator import itemgetter from libs import easing @@ -25,6 +25,7 @@ from keys_def import CurKeys from label import Label from untitled_icon import UntitledIcon from Emulator import MyEmulator +from CommercialSoftwarePackage import MyCommercialSoftwarePackage from skin_manager import MySkinManager from lang_manager import MyLangManager @@ -120,6 +121,7 @@ class MessageBox(Label): python_package_flag = "__init__.py" emulator_flag = "action.config" +commercialsoftware_flag = "compkginfo.json" ##Abstract object for manage Pages ,not the pygame's physic screen class MainScreen(Widget): @@ -383,7 +385,14 @@ class MainScreen(Widget): if i.endswith(emulator_flag): return True return False - + + def IsCommercialPackage(self,dirname): + files = os.listdir(dirname) + for i in sorted(files): + if i.endswith(commercialsoftware_flag): + return True + return False + def IsPythonPackage(self,dirname): files = os.listdir(dirname) for i in sorted(files): @@ -435,6 +444,7 @@ class MainScreen(Widget): def ReadTheDirIntoPages(self,_dir,pglevel,cur_page): + global commercialsoftware_flag if FileExists(_dir) == False and os.path.isdir(_dir) == False: return @@ -523,11 +533,30 @@ class MainScreen(Widget): iconitem._MyType = ICON_TYPES["Emulator"] cur_page._Icons.append(iconitem) - elif self.IsExecPackage(_dir+"/"+i): + elif self.IsCommercialPackage( os.path.join(_dir,i)): + data = None + em = MyCommercialSoftwarePackage() + if FileExists( _dir+"/"+i+"/.done"): + print(_dir+"/"+i+"/.done") + em._Done = os.path.realpath(_dir+"/"+i+"/"+i2+".sh") + else: + with open(os.path.join(_dir,i) +"/"+commercialsoftware_flag) as f: + data = json.load(f) + em._ComPkgInfo = data + em._Done = "" + + em._InvokeDir = os.path.realpath( os.path.join(_dir,i)) + em.Init(self) + + iconitem._CmdPath = em + iconitem._MyType = ICON_TYPES["Commercial"] + cur_page._Icons.append(iconitem) + + elif self.IsExecPackage(_dir+"/"+i): ## ExecPackage is the last one to check iconitem._MyType = ICON_TYPES["EXE"] iconitem._CmdPath = os.path.realpath(_dir+"/"+i+"/"+i2+".sh") MakeExecutable(iconitem._CmdPath) - cur_page._Icons.append(iconitem) + cur_page._Icons.append(iconitem) else: iconitem._MyType = ICON_TYPES["DIR"] iconitem._LinkPage = Page() diff --git a/sys.py/UI/page.py b/sys.py/UI/page.py index 8e2c1ab..b734c0e 100644 --- a/sys.py/UI/page.py +++ b/sys.py/UI/page.py @@ -98,6 +98,8 @@ class Page(Widget): _SelectedIconTopOffset=20 _EasingDur = 30 + _Padding = pygame.Rect(0,0,0,0)# x,y,w,h + _Margin = pygame.Rect(0,0,0,0) def __init__(self): self._Icons = [] @@ -519,7 +521,7 @@ class Page(Widget): if api_cb != None: if callable(api_cb): cur_icon._CmdPath.API(self._Screen) - elif cur_icon._MyType == ICON_TYPES["Emulator"]: + elif cur_icon._MyType == ICON_TYPES["Emulator"] or cur_icon._MyType == ICON_TYPES["Commercial"]: cur_icon._CmdPath.API(self._Screen) def ReturnToUpLevelPage(self): diff --git a/sys.py/UI/text_bulletinboard.py b/sys.py/UI/text_bulletinboard.py index 2892272..017458c 100644 --- a/sys.py/UI/text_bulletinboard.py +++ b/sys.py/UI/text_bulletinboard.py @@ -112,12 +112,12 @@ class Textbulletinboard(Textarea): _TextLimit = 200 _BackgroundColor = MySkinManager.GiveColor("White") _Align = "Left" ## Left or Center + _RowPitch = -1 def SetAndBlitText(self,words):# words => [] if self._TextFull != True: self._MyWords = words - #self.BlitText() self._TextIndex = len(self._MyWords) else: print("is Full %s" % "".join(str(self._MyWords))) @@ -130,13 +130,15 @@ class Textbulletinboard(Textarea): x = self._PosX+xmargin linenumber = 0 cursor_row = 0 - + + #print(self._MyWords) for i, v in enumerate(self._MyWords): if str(v) == "\n": w = 0 x = self._PosX+xmargin - linenumber+=1 - blit_rows.append([]) + linenumber+=2 + blit_rows.append([]) + blit_rows.append([]) else: t = v.Render() t_width = t.get_width() @@ -153,8 +155,7 @@ class Textbulletinboard(Textarea): w = 0 linenumber += 1 blit_rows.append([]) - - + self._BlitWords = blit_rows self._BlitIndex = self._TextIndex @@ -171,10 +172,13 @@ class Textbulletinboard(Textarea): self._TextFull = len(self._MyWords) > self._TextLimit last_height = 0 - for row_idx, row in enumerate(self._BlitWords): - + for row_idx, row in enumerate(self._BlitWords): if len(row) == 0: - y = y + 16 + if self._RowPitch > 0: + y = y + self._RowPitch + else: + y = y + 16 + w = 0 continue @@ -194,6 +198,7 @@ class Textbulletinboard(Textarea): last_height = 0 total_row_width = 0 x = start_x + y = y + last_height for i,v in enumerate(row): t = v.Render() total_row_width += t.get_width() @@ -208,9 +213,7 @@ class Textbulletinboard(Textarea): self._CanvasHWND.blit(t, (x,y)) x += t.get_width() - - y = y + last_height - + def Draw(self): #aa_round_rect(self._CanvasHWND, (4,24.5+6,312,60),self._BackgroundColor,4,0,self._BackgroundColor)