init 2 python: import json # CONST PARAMS ALLOW_ZOOM = False GALLERY_COLS = 4 PREFERRED_WIDTH = 432 #px (1920 * 0.225) PREFERRED_HEIGHT = 243 #px (1080 * 0.225) PREFERRED_ASPECT_RATIO = 16.0/9.0 # 1.7777.. DEFAULT_WIDTH_SCALE_RATIO = round(float(PREFERRED_WIDTH) / float(1920), 4) DEFAULT_HEIGHT_SCALE_RATIO = round(float(PREFERRED_HEIGHT) / float(1080), 4) NOT_UNLOCKED_COVER = im.FactorScale("gui/gallery/unlocked_cg_button_cover.png", DEFAULT_WIDTH_SCALE_RATIO, DEFAULT_HEIGHT_SCALE_RATIO) ACCEPTED_EXTENSIONS = ["jpg", "png", "webm"] CG_PATHS = [ #CG doesn't really make sense { 'path': "images/cgs/", 'name': "CG", 'eval': None }, { 'path': "images/animations/", 'name': "Animations", 'eval': None }, { 'path': "images/NotForKids!/", 'name': "Lewd", 'eval': 'persistent.lewd == True' } ] #path: folder, name: shows up in gallery, eval: runs eval() on string """ Data structure that holds the data for each cg and button item is name, fn is fullpath ext is the file extension { item: str; fn: str; cg: Displayable; ext: str; wh: [] }[] (reference in this init python, actually used in screens) """ gallery_items = [] # key dict pair, cg <-> cgs' galleryitems [] gallery_dic = {} # for cp in CG_PATHS: gallery_dic[cp['name']] = [] # # Make a scaled cg button # (cg: string; ext: string; w: float def cg_(fname, ext, w): scale = PREFERRED_WIDTH / w #scale = box_ratio(wh) #image = im.FactorScale(fname, scale, scale, True) if type(fname) is str: image = im.FactorScale(fname, scale, scale, True) return image else: return Transform(fname, zoom=scale) #return Transform(fname, crop=(0,0,1920,1080), zoom=scale) # Reads /images/cgs dir for all image files # Populates galleryItems # () -> None def add_(str, _str, ext, cpname): image = renpy.image_size(Image(_str)) item = { "item": str, "fn": _str, "cg": cg_(_str, ext, image[0]), "ext": ext, "wh": image } gallery_dic[cpname].append(item) pass def loadGallery(): list_img = renpy.list_images() #if ext is "webm": # Add each image to the gallery for str in list_img: for cp in CG_PATHS: for ext in ACCEPTED_EXTENSIONS: path = cp['path'] _str = path+str+"."+ext if renpy.loadable(_str): #brute force add_(str, _str, ext, cp['name']) return # Call to loading the gallery loadGallery() #renpy.start_predict_screen("cg_gallery") #sort # hard code the webm because renpy is really dumb and doesn't add Movies properly until much later fang_webm = 'fang thumb' webm_rcg = Fixed(Color("#000"), Text("Fang", size=280, xalign=0.5, yalign=0.5), xsize=1920) renpy.seen_label('fang_movie') gallery_dic['Animations'] = [{ "item": 'fang tail', "fn": 'fang tail', "cg": cg_('images/backgrounds/garden.jpg', None, 1920), "ext": 'webm', "wh": [1920, 1080] }] #for zooming in and out zoom_arr = [0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.5, 1.75, 2.0] """ for x in range(1,5): _zoom = 1.0 _zoom *= 1+(x*0.25) zoom_arr.append(_zoom) for y in range(9,1,-1): _zoom = 1.0 _zoom *= (y*0.125) zoom_arr.append(_zoom) zoom_arr.sort() """ def jsonloadandpop(): #CACHE_PATH = config.basedir.replace("\\","/") + "/game/cache/" FILENAME = os.path.join(config.basedir, 'game/src/gallery_dataset.json') #CACHE_PATH = config.basedir.replace("\\","/") + "/game/cache/" fp = open(FILENAME) data = json.load(fp) list_img = renpy.list_images() for x in data['tabs']: tab_name = x['tab_name'] _eval = None if 'eval' in x.keys(): _eval = x['eval'] CG_PATHS.append({'path': None, 'name': tab_name, 'eval': _eval}) gallery_dic[tab_name] = [] #gallery_dataset if 'items' in x.keys(): for y in x['items']: name = y["name"] cg = y["image"] rcg = renpy.get_registered_image(cg) #print(rcg.get_size()) image_dimensions = (1920, 1080) #renpy.image_size(rcg) item = { "item": name, "fn": rcg, "cg": cg_(rcg, None, image_dimensions[0]), "ext": None, "wh": image_dimensions } gallery_dic[tab_name].append(item) else: #folders for str in list_img: for cp in x['folders']: for ext in ACCEPTED_EXTENSIONS: path = cp #cp['path'] _str = path+str+"."+ext #print(_str) if renpy.loadable(_str): #brute force add_(str, _str, ext, tab_name) #cp['name']) #print(data) pass jsonloadandpop() pass """ 'Recursive' / Loopable / Roundtrip Screens _0 <-> _1 """ #There is renpy.restart_interaction but since I wrote all this, it's too late #screen cg_gallery(flag, __yoffset = 0, origin = 'CG'): screen cg_gallery_0(__yoffset = 0, origin = 'CG'): tag menu use cg_gallery('1', __yoffset, origin) screen cg_gallery_1( __yoffset = 0, origin = 'CG'): tag menu use cg_gallery('0', __yoffset, origin) #screen view_image(fn, _origin, zoom=1): screen view_image_a(fn, _origin = 0, zoom = zoom_arr.index(1.0)): tag menu use view_image(fn, _origin, zoom, 'b') screen view_image_b(fn, _origin, zoom = zoom_arr.index(1.0)): tag menu use view_image(fn, _origin, zoom, 'a') """ CG Gallery screen - A screen that shows the image gallery Basically Gallery Object has terrible defaults, so I just wrote my own stuff """ screen cg_gallery(flag, __yoffset = 0, origin = 'CG'): if main_menu: key "game_menu" action ShowMenu("main_menu") frame: pass add gui.main_menu_background add gui.game_menu_background tag menu python: empty_spaces = gallery_rows = item_counter = 0 gallery_items = gallery_dic[origin] items = len(gallery_items) gallery_rows = (items / GALLERY_COLS) + 1 empty_spaces = GALLERY_COLS - (items % GALLERY_COLS) vbox: transform: zoom 0.95 hbox: style_prefix "navigation" xalign 0.5 spacing gui.navigation_spacing for cp in CG_PATHS: if cp['name'] == origin: textbutton _(cp['name']) text_color gui.selected_color text_xalign 0.5 else: if cp['eval'] is None: textbutton _(cp['name']) activate_sound "audio/ui/uiClick.wav" action ShowMenu('cg_gallery_'+flag, 0, cp['name']) text_xalign 0.5 elif eval(cp['eval']): textbutton _(cp['name']) activate_sound "audio/ui/uiClick.wav" action ShowMenu('cg_gallery_'+flag, 0, cp['name']) text_xalign 0.5 else: textbutton _(cp['name']) text_xalign 0.5 textbutton _("Return") activate_sound "audio/ui/uiBack.wav" action ShowMenu('main_menu') text_xalign 0.5 if _in_replay: textbutton _("End Replay") activate_sound "audio/ui/uiBack.wav" action EndReplay(confirm=True) elif not main_menu: textbutton _("Main Menu") activate_sound "audio/ui/uiBack.wav" action MainMenu() transform: zoom 0.95 xcenter 0.525 ycenter 0.525 vpgrid id "vpg": #yinitial __yoffset scrollbars "vertical" mousewheel True draggable True pagekeys True xfill True xcenter 0.5 #ycenter 0.5 spacing 20 #rows gallery_rows cols GALLERY_COLS for item in gallery_items: # Should properly fix with actual margin difference but good # enough or the actual position python: item_counter += 1 #yoffset = int( yoffset + (PREFERRED_HEIGHT * 1.15)) yoffset = int(item_counter / 3 * PREFERRED_HEIGHT + ((item_counter / 3))) use flag_button(item, yoffset, origin) for i in range(0, empty_spaces): null height 20 """ if/else flow control & extra parameters for Buttons """ screen flag_button(item, yoffset, origin): python: flag = renpy.seen_image(item['item']) if flag: button: if item['ext'] == "webm": action Replay('fang_movie')#ShowMenu('view_movie', item, ShowMenu('cg_gallery_0', yoffset, origin)) else: action ShowMenu('view_image_a', item, ShowMenu('cg_gallery_0', yoffset, origin)) #action Show('view_image', None, item, ShowMenu('cg_gallery_0', yoffset, origin), _zorder=1) xcenter 0.5 ycenter 0.5 padding (1,0,1,2) vbox: text item["item"] xalign 0.5 add item["cg"] fit 'contain' xcenter 0.5 ycenter 0.5 size (PREFERRED_WIDTH, PREFERRED_HEIGHT) else: vbox: ymaximum PREFERRED_HEIGHT xcenter 0.5 ycenter 0.5 text "? ? ?" xalign 0.5 add NOT_UNLOCKED_COVER screen view_movie(item, _origin): tag menu key "game_menu" action _origin python: renpy.movie_cutscene(item['item'], None, -1) frame: pass #scene fang tail with fade """ view_image, Loads the image in fullscreen with viewport control. """ screen view_image(item, _origin, zoom = zoom_arr.index(1.0), flag='a'): python: #_origin = Show('cg_gallery_0', 0, _origin) zoom_a = zoom+1 zoom_a_f = ShowMenu('view_image_'+flag, item, _origin, zoom_a) zoom_b = zoom-1 zoom_b_f = ShowMenu('view_image_'+flag, item, _origin, zoom_b) tag menu key "game_menu" action [Hide('view_image'), _origin ] #Show('cg_gallery_0')] #_origin key "button_alternate" action [Hide('view_image'), _origin ] # Show('cg_gallery_0')] #key "button_alternate" action _origin # mousewheel & insert+delete if (ALLOW_ZOOM): if zoom < len(zoom_arr)-1: #zoom in key 'mousedown_4' action zoom_a_f key 'K_INSERT' action zoom_a_f if zoom > 0: #and (item['wh'][0] <= 1920 or item['wh'][1] <= 1080): key 'mousedown_5' action zoom_b_f key 'K_DELETE' action zoom_b_f viewport id "vie": #Ren'Py isn't smart enough to not edgescroll while pressed, #so we'll have to disable this for mobile if renpy.variant("pc"): edgescroll (300, 1800) draggable True arrowkeys True pagekeys True xfill False yfill False add item['fn'] zoom zoom_arr[zoom] anchor (0.55, 0.55) #Reuse quick buttons, Ren'Py handles touch input lazy, it doesn't have #double finger pinch zoom, it translates taps as mouse events - have to use #buttons hbox: style_prefix "quick" xalign 0.5 yalign 0.975 if (ALLOW_ZOOM) and renpy.variant("small"): use quick_buttons("gui/button/uioptionbuttons/template_idle.png", [ [ "+", zoom_a_f ], [ "-", zoom_b_f ], [ "Return", zoom_b_f ] ] ) elif renpy.variant("small"): use quick_buttons("gui/button/uioptionbuttons/template_idle.png", [ [ "Return", _origin ] ] )