1import ctypes 2import os 3import sys 4import time 5from collections import deque 6 7from arcade.gamecentersettings import ArcadeSettings 8from fsbc import settings 9from fsgs.FSGSDirectories import FSGSDirectories 10 11from arcade.gamecenter import GameCenter 12from arcade.resources import resources 13from fsbc.system import windows 14from fsgs.option import Option 15from fsgs.platform import PlatformHandler 16from fsgs.util.gamenameutil import GameNameUtil 17 18# from arcade.main import Main 19from arcade.resources import logger 20from arcade.glui.opengl import gl, fs_emu_texturing, fs_emu_blending 21from arcade.glui.settings import Settings 22from arcade.glui.sdl import SDL_IsMinimized 23from arcade.glui.imageloader import ImageLoader 24from arcade.glui.itemmenu import ItemMenu 25from arcade.glui.displaylists import DisplayLists 26from arcade.glui.bezier import Bezier 27from arcade.glui.input import InputHandler 28from arcade.glui.animation import AnimationSystem 29from arcade.glui.animation import AnimateValueBezier 30from arcade.glui.state import State 31from arcade.glui.render import Render 32from arcade.glui.notificationrender import NotificationRender 33from arcade.glui.font import Font, BitmapFont 34from arcade.glui.items import MenuItem, AllMenuItem, NoItem, PlatformItem 35from arcade.glui.items import ListItem 36from arcade.glui.texture import Texture 37from arcade.glui.texturemanager import TextureManager 38from arcade.glui.constants import TOP_HEIGHT 39 40# FIXME: rename to manager or director or somethign 41main_window = None 42 43# ENABLE_VSYNC = Config.get_bool("Menu/VSync", True) 44ENABLE_VSYNC = "--vsync" in sys.argv 45ALWAYS_RENDER = True 46# IDLE = Config.get_bool("Menu/Idle", 1) 47IDLE = 1 48if "--no-idle" in sys.argv: 49 IDLE = 0 50# Render.get().display_fps = pyapp.user.ini.get_bool("Menu/ShowFPS", False) 51# LIGHTING = Config.get_bool("Menu/Lighting", False) 52LIGHTING = False 53RENDER_DEBUG_SQUARES = 0 54if "--render-debug-squares" in sys.argv: 55 RENDER_DEBUG_SQUARES = 1 56SEARCH_CHARS = ( 57 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -:.," 58) 59CONFIG_SEPARATION = 0.15 60ANIMATION_SETTLE_TIME_1 = 1.0 61ANIMATION_SETTLE_TIME_2 = 2.0 62 63force_display_ratio = None 64display = None 65real_display_height = 0 66current_menu = None 67last_menu = None 68last_game = None 69 70 71def get_current_time(): 72 return time.time() 73 74 75def set_current_menu(menu): 76 if not isinstance(menu, SearchResultsMenu): 77 menu.search_text = "" 78 79 global current_menu 80 if len(menu) == 0: 81 menu.append(NoItem()) 82 current_menu = menu 83 State.get().current_menu = menu 84 if menu.navigatable: 85 State.get().navigatable = menu.navigatable 86 else: 87 State.get().navigatable = menu 88 State.get().top_menu = menu.top 89 State.get().down_navigatable = None 90 Render.get().dirty = True 91 92 93# WINDOWED_SIZE = [1024, 640] # 16:10 94# WINDOWED_SIZE = (1024, 576) # 16:9 95# WINDOWED_SIZE = [1024, 768] # 4:3 96# WINDOWED_SIZE = [960, 540] # 16:9 97WINDOWED_SIZE = [1280, 720] # 16:9 98 99RENDER_GAME = ["IMAGE", "REFLECTIONS", "SCREENSHOTS"] 100RENDER_GAME_OVERLAY = ["TITLE", "HEADER"] 101 102# USE_MENU_TRANSITIONS = pyapp.user.ini.get_bool("Menu/Transitions", True) 103# if "--disable-shaders" in sys.argv: 104# USE_MENU_TRANSITIONS = False 105USE_MENU_TRANSITIONS = False 106FIELD_COLOR = 0.1 107WALL_COLOR = 0.0 108# IDLE_EVENT = pygame.NUMEVENTS - 1 109DEFAULT_ITEM_BRIGHTNESS = 0.8 110 111 112class MenuGameTransition(object): 113 value = 0.0 114 115 116class MenuForwardTransition(object): 117 # must be initially set to 1 because this indicates that 118 # the transition is done / not in progress 119 value = 1.0 120 121 122class MenuBackwardTransition(object): 123 # must be initially set to 1 because this indicates that 124 # the transition is done / not in progress 125 value = 1.0 126 127 128class ScreenshotTransition(object): 129 anim = None 130 # must be initially set to 1 because this indicates that 131 # the transition is done / not in progress 132 value = 1.0 133 134 135class RunTransition(object): 136 value = 0.0 137 138 139class Mouse(object): 140 items = [] 141 focus = None 142 143 @classmethod 144 def set_visible(cls, visible=True): 145 assert visible is not None 146 # if State.get().mouse_visible == visible: 147 # return 148 # if not visible: 149 # cls.focus = None 150 # pygame.mouse.set_visible(visible) 151 # State.get().mouse_visible = visible 152 print("Mouse.set_visible not implemented") 153 154 155def set_items_brightness(brightness, duration=1.0, delay=0.0): 156 State.get().items_brightness_anim = AnimateValueBezier( 157 (State, "items_brightness"), 158 State.get().items_brightness, 159 State.get().time + delay, 160 State.get().items_brightness, 161 State.get().time + delay, 162 brightness, 163 State.get().time + delay + duration, 164 brightness, 165 State.get().time + delay + duration, 166 ) 167 168 169def compile_shader(source, shader_type): 170 shader = gl.glCreateShaderObjectARB(shader_type) 171 gl.glShaderSourceARB(shader, source) 172 gl.glCompileShaderARB(shader) 173 try: 174 status = ctypes.c_int() 175 gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS, ctypes.byref(status)) 176 status = status.value 177 except TypeError: 178 status = gl.glGetShaderiv(shader, gl.GL_COMPILE_STATUS) 179 if not status: 180 print_log(shader) 181 gl.glDeleteObjectARB(shader) 182 raise ValueError("Shader compilation failed") 183 return shader 184 185 186def compile_program(vertex_source, fragment_source): 187 vertex_shader = None 188 fragment_shader = None 189 program = gl.glCreateProgram() 190 if vertex_source: 191 print("compile vertex shader") 192 vertex_shader = compile_shader(vertex_source, gl.GL_VERTEX_SHADER) 193 gl.glAttachShader(program, vertex_shader) 194 if fragment_source: 195 print("compile fragment shader") 196 fragment_shader = compile_shader( 197 fragment_source, gl.GL_FRAGMENT_SHADER 198 ) 199 gl.glAttachShader(program, fragment_shader) 200 gl.glLinkProgram(program) 201 status = gl.glGetProgramiv(program, gl.GL_LINK_STATUS) 202 if status == gl.GL_FALSE: 203 print("could not link shader program") 204 print(gl.glGetProgramInfoLog(program)) 205 sys.exit(1) 206 if vertex_shader: 207 gl.glDeleteShader(vertex_shader) 208 if fragment_shader: 209 gl.glDeleteShader(fragment_shader) 210 return program 211 212 213def print_log(shader): 214 length = ctypes.c_int() 215 gl.glGetShaderiv(shader, gl.gl.GL_INFO_LOG_LENGTH, ctypes.byref(length)) 216 if length.value > 0: 217 shader_log = gl.glGetShaderInfoLog(shader) 218 print(shader_log) 219 sys.exit(1) 220 221 222texture_program = None 223color_program = None 224premultiplied_texture_program = None 225 226 227def compile_programs(): 228 global texture_program, color_program, premultiplied_texture_program 229 vertex_shader = None 230 231 color_program = compile_program( 232 vertex_shader, 233 [ 234 """ 235void main() 236{ 237vec4 s = gl_Color; 238float extra_alpha = 1.0; 239//float extra_alpha = gl_TextureEnvColor[0].a; 240float a = s.a * extra_alpha; 241gl_FragColor.a = a; 242gl_FragColor.r = s.r*a; 243gl_FragColor.g = s.g*a; 244gl_FragColor.b = s.b*a; 245} 246 """ 247 ], 248 ) 249 250 texture_program = compile_program( 251 vertex_shader, 252 [ 253 """ 254uniform sampler2D texture; 255 256void main() 257{ 258vec4 s = texture2D(texture,gl_TexCoord[0].st); 259//float extra_alpha = 1.0; 260//float extra_alpha = gl_TextureEnvColor[0].a; 261float opacity = gl_Color.a; 262float a = s.a * opacity; 263gl_FragColor.a = a; 264gl_FragColor.r = s.r * a; 265gl_FragColor.g = s.g * a; 266gl_FragColor.b = s.b * a; 267} 268""" 269 ], 270 ) 271 272 premultiplied_texture_program = compile_program( 273 vertex_shader, 274 [ 275 """ 276uniform sampler2D texture; 277 278void main() 279{ 280vec4 s = texture2D(texture,gl_TexCoord[0].st); 281//float extra_alpha = 1.0; 282//float extra_alpha = gl_TextureEnvColor[0].a; 283float opacity = gl_Color.a; 284gl_FragColor.a = s.a * opacity; 285gl_FragColor.r = s.r * opacity; 286gl_FragColor.g = s.g * opacity; 287gl_FragColor.b = s.b * opacity; 288} 289""" 290 ], 291 ) 292 293 294def enable_texture_shader(): 295 fs_emu_blending(True) 296 gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA) 297 gl.glUseProgram(texture_program) 298 299 300def disable_shader(): 301 gl.glUseProgram(0) 302 303 304def set_program(program): 305 if not program: 306 gl.glUseProgram(0) 307 else: 308 gl.glUseProgram(program) 309 310 311def enter_menu(result, replace=False): 312 print("enter_menu", result, "replace", replace) 313 print(" menu parent_menu", result.parent_menu) 314 315 if replace: 316 State.get().history.pop() 317 c_menu = State.get().history[-1] 318 result.parents[:] = c_menu.parents 319 result.parents.append(c_menu) 320 print(" menu parents ", result.parents) 321 State.get().history.append(result) 322 set_current_menu(result) 323 324 325def create_main_menu(): 326 new_menu = AllMenuItem().activate(None) 327 if len(new_menu) == 0: 328 new_menu.append(NoItem()) 329 return new_menu 330 331 332def recreate_main_menu_if_necessary(): 333 new_menu = create_main_menu() 334 State.get().history.append(new_menu) 335 set_current_menu(new_menu) 336 337 338def show(): 339 global current_menu 340 341 # fade_from is used on init_display, so we initialize this 342 # color here. Set alpha to 2.0 to force 1 second of solid 343 # color in combination with 2 sec. animation below 344 if False and windows and not Settings.fullscreen_menu: 345 State.get().fade_from = (1.0, 1.0, 1.0, 2.0) 346 State.get().fade_to = (1.0, 1.0, 1.0, 0.0) 347 else: 348 State.get().fade_from = (0.0, 0.0, 0.0, 2.0) 349 State.get().fade_to = (0.0, 0.0, 0.0, 0.0) 350 init_display() 351 if LIGHTING: 352 init_lighting() 353 init_textures() 354 init_fonts() 355 356 if USE_MENU_TRANSITIONS: 357 compile_programs() 358 359 InputHandler.open() 360 361 on_resize((Render.get().display_width, Render.get().display_height)) 362 image_loader = ImageLoader.get() 363 image_loader.start() 364 new_menu = create_main_menu() 365 State.get().history.append(new_menu) 366 367 override_items = [] 368 for platform_id in PlatformHandler.get_platform_ids(): 369 if "--platform=" + platform_id in sys.argv: 370 sys.argv.remove("--platform=" + platform_id) 371 platform_item = PlatformItem(platform_id) 372 override_items.append(platform_item) 373 break 374 # if "--favorites" in sys.argv or \ 375 # settings.get(Option.ARCADE_INITIAL_VIEW) == "favorites": 376 if ( 377 "--favorites" in sys.argv 378 or settings.get(Option.ARCADE_INITIAL_FAVORITES) == "1" 379 ): 380 if "--favorites" in sys.argv: 381 sys.argv.remove("--favorites") 382 try: 383 list_uuid = ListItem.get_favorites_uuid() 384 favorites_item = ListItem("Favorites", list_uuid) 385 except LookupError: 386 print("No favorites list") 387 # noinspection SpellCheckingInspection 388 favorites_item = ListItem( 389 "Favorites", "c03dd5fe-0e85-4efb-a126-f0e4f40feae6" 390 ) 391 override_items.append(favorites_item) 392 if override_items: 393 parent_menu = new_menu 394 override_menu = None 395 parents = [] 396 for item in override_items: 397 override_menu = ItemMenu() 398 override_menu.parent_menu = parent_menu 399 parents.append(parent_menu) 400 # This is really hackish 401 override_menu.parents = parents 402 override_menu.items.append(item) 403 parent_menu = override_menu 404 new_menu = override_items[-1].activate(override_menu) 405 print(new_menu) 406 State.get().history.append(new_menu) 407 408 set_current_menu(new_menu) 409 if len(new_menu) == 1: 410 # only n/a item showing, possibly 411 if len(AllMenuItem().activate(None)) == 0: 412 # no games, initiate game scan 413 rescan_games() 414 415 State.get().fade_start = get_current_time() 416 State.get().fade_end = get_current_time() + 2.000 417 418 # # make a timer so that update events are sent to modules at least once 419 # # every second 420 # pygame.time.set_timer(IDLE_EVENT, 1000) 421 422 State.get().start_time = get_current_time() 423 424 425def init_fonts(): 426 NotificationRender.init() 427 428 BitmapFont.title_font = BitmapFont("title_font") 429 BitmapFont.menu_font = BitmapFont("menu_font") 430 431 432liberation_sans_bold_path = None 433liberation_sans_narrow_bold_path = None 434vera_font_path = None 435 436 437def find_font_path_or_stream(name): 438 path = os.path.join( 439 FSGSDirectories.get_base_dir(), "Workspace", "Fonts", name 440 ) 441 if os.path.exists(path): 442 return path 443 stream = resources.resource_stream(name) 444 return stream 445 446 447def reinit_fonts(): 448 print( 449 "reinit_fonts, Render.get().display_height =", 450 Render.get().display_height, 451 ) 452 global liberation_sans_bold_path 453 global liberation_sans_narrow_bold_path 454 global vera_font_path 455 456 if liberation_sans_bold_path is None: 457 liberation_sans_bold_path = find_font_path_or_stream( 458 "LiberationSans-Bold.ttf" 459 ) 460 461 # if liberation_sans_narrow_bold_path is None: 462 # liberation_sans_narrow_bold_path = resources.resource_filename( 463 # "LiberationSansNarrow-Bold.ttf") 464 # if vera_font_path is None: 465 # vera_font_path = resources.resource_filename( 466 # "VeraBd.ttf") 467 468 if Font.title_font is None: 469 Font.title_font = Font( 470 liberation_sans_bold_path, int(0.04 * Render.get().display_height) 471 ) 472 Font.title_font.set_size(int(0.04 * Render.get().display_height)) 473 if Font.subtitle_font is None: 474 Font.subtitle_font = Font( 475 liberation_sans_bold_path, int(0.025 * Render.get().display_height) 476 ) 477 Font.subtitle_font.set_size(int(0.025 * Render.get().display_height)) 478 # if Font.small_font is None: 479 # Font.small_font = Font( 480 # liberation_sans_narrow_bold_path, 481 # int(0.025 * Render.get().display_height)) 482 # Font.small_font.set_size(int(0.025 * Render.get().display_height)) 483 if Font.main_path_font is None: 484 Font.main_path_font = Font( 485 liberation_sans_bold_path, int(0.025 * Render.get().display_height) 486 ) 487 Font.main_path_font.set_size(int(0.025 * Render.get().display_height)) 488 if Font.list_subtitle_font is None: 489 Font.list_subtitle_font = Font( 490 liberation_sans_bold_path, int(0.020 * Render.get().display_height) 491 ) 492 Font.list_subtitle_font.set_size(int(0.020 * Render.get().display_height)) 493 # if Font.header_font is None: 494 # Font.header_font = Font( 495 # vera_font_path, int(0.06 * Render.get().display_height)) 496 # Font.header_font.set_size(int(0.06 * Render.get().display_height)) 497 498 if NotificationRender.font is None: 499 NotificationRender.font = Font( 500 liberation_sans_bold_path, int(0.020 * Render.get().display_height) 501 ) 502 503 504char_buffer = "" 505char_buffer_last_updated = 0 506 507 508def handle_search_menu_on_character_press(char_buffer): 509 # if len(char_buffer) > 2 and t - char_buffer_last_updated > 0.5: 510 if len(char_buffer) > 2: 511 print(char_buffer) 512 create_search_results_menu(char_buffer) 513 if len(char_buffer) <= 2: 514 if isinstance(current_menu, SearchResultsMenu): 515 # collapse search menu 516 517 # if hasattr(current_menu, "search_text"): 518 print("setting current_menu (something with search)") 519 # set_current_menu(current_menu.parent_menu) 520 go_back() 521 else: 522 current_menu.search_text = char_buffer 523 524 525# noinspection PyUnusedLocal 526def character_press(char): 527 print("character press", repr(char)) 528 if State.get().current_game: # or isinstance(current_menu, GameMenu): 529 print("ignoring key press", repr(char)) 530 return 531 532 # global char_buffer 533 char_buffer = current_menu.search_text 534 535 global char_buffer_last_updated 536 char_buffer_last_updated = State.get().time 537 # return 538 539 Render.get().dirty = True 540 if char == "RETURN": 541 print(char_buffer, len(char_buffer)) 542 print("returning false") 543 return False 544 elif char == "BACKSPACE" or char == u"\b": 545 if ArcadeSettings().search(): 546 char_buffer = char_buffer[:-1] 547 if len(char_buffer) <= 2: 548 char_buffer = "" 549 handle_search_menu_on_character_press(char_buffer) 550 return True 551 elif len(char) == 1: 552 if ArcadeSettings().search(): 553 char_buffer += char 554 handle_search_menu_on_character_press(char_buffer) 555 if 1 <= len(char_buffer) <= 2: 556 jump_to_item = -1 557 for i, item in enumerate(current_menu.items): 558 # FIXME: a bit hack-y this, should check sort_name 559 # instead (need to store this in items then) 560 # also, should use binary search and not sequential search 561 searches = [ 562 char_buffer, 563 "the " + char_buffer, 564 "a " + char_buffer, 565 ] 566 check = item.name.lower() 567 for s in searches: 568 if check.startswith(s): 569 jump_to_item = i 570 break 571 if jump_to_item >= 0: 572 current_menu.set_selected_index( 573 jump_to_item, immediate=True 574 ) 575 return True 576 else: 577 raise Exception(repr(char)) 578 579 580class SearchTextItem(MenuItem): 581 def __init__(self, title): 582 MenuItem.__init__(self) 583 self.path_title = title 584 585 586class SearchResultsMenu(ItemMenu): 587 pass 588 589 590def create_search_results_menu(text): 591 global current_menu 592 try: 593 if text == current_menu.search_text: 594 return False 595 except AttributeError: 596 pass 597 new_menu = SearchResultsMenu("Search Results") 598 new_menu.search_text = text 599 # words = [v.strip() for v in text.lower().split(" ")] 600 # print "Creating search results for", words 601 new_menu.top.append_left(SearchTextItem("Search: {0}_".format(text))) 602 new_menu.top.set_selected_index( 603 len(new_menu.top.left) + len(new_menu.top.right) - 1 604 ) 605 606 # clause = [] 607 # args = [] 608 # for word in words: 609 # clause.append("AND name like ?") 610 # args.append("%{0}%".format(word)) 611 # clause = " ".join(clause) 612 terms = GameNameUtil.extract_search_terms(text.lower()) 613 for item in MenuItem.create_game_items(terms): 614 new_menu.append(item) 615 if len(new_menu) == 0: 616 new_menu.append(NoItem("No Search Results")) 617 # if hasattr(current_menu, "search_text"): 618 # # replace current search menu, not append to path 619 # #new_menu.parent_menu = current_menu.parent_menu 620 # replace = True 621 # else: 622 # #new_menu.parent_menu = current_menu 623 # replace = False 624 replace = isinstance(current_menu, SearchResultsMenu) 625 print("create search results menu") 626 # set_current_menu(new_menu) 627 enter_menu(new_menu, replace=replace) 628 return True 629 630 631def rescan_games(): 632 # global current_menu 633 print("rescan games -- currently disabled") 634 # GameScanner.scan() 635 # Render.get().dirty = True 636 pass 637 638 639def go_back(): 640 c_menu = State.get().history[-1] 641 if hasattr(c_menu, "go_back"): 642 c_menu.go_back() 643 return 644 State.get().history.pop() 645 set_current_menu(State.get().history[-1]) 646 647 648def default_input_func(button): 649 if button == "LEFT": 650 State.get().navigatable.go_left() 651 elif button == "RIGHT": 652 State.get().navigatable.go_right() 653 elif button == "UP": 654 State.get().navigatable.go_up() 655 elif button == "DOWN": 656 State.get().navigatable.go_down() 657 elif button == "SKIP_LEFT": 658 State.get().navigatable.go_left(10) 659 elif button == "SKIP_RIGHT": 660 State.get().navigatable.go_right(10) 661 elif button == "PRIMARY": 662 663 # global char_buffer 664 # char_buffer = "" 665 666 State.get().navigatable.activate() 667 668 elif button == "BACK": 669 print("-- button is BACK -- ") 670 if State.get().config_menu: 671 State.get().config_menu = None 672 set_current_menu(State.get().current_menu) 673 set_items_brightness(0.66, duration=0.500) 674 elif State.get().current_game is None and current_menu.search_text: 675 InputHandler.get_button() # clear OK status 676 character_press("BACKSPACE") 677 elif State.get().current_game: 678 State.get().current_game = None 679 # game_fade_animation = AnimateValueBezier( 680 # (MenuGameTransition, "value"), 681 # 1.0, State.get().time, 682 # 1.0, State.get().time + 0.133, 683 # 0.0, State.get().time + 0.133, 684 # 0.0, State.get().time + 0.400) 685 686 # elif can_navigate and current_menu.parent_menu: 687 # elif can_navigate and len(State.get().history) > 1: 688 elif len(State.get().history) > 1: 689 go_back() 690 elif button == "QUIT": 691 State.get().quit = True 692 693 694def render_top(): 695 Render.get().hd_perspective() 696 gl.glPushMatrix() 697 transition = State.get().current_menu.top_menu_transition 698 gl.glTranslate(0.0, (1.0 - transition) * 90, 0.9) 699 700 gl.glTranslate(0.0, 0.0, 0.05) 701 702 if State.get().top_menu == State.get().navigatable: 703 selected_index = State.get().top_menu.get_selected_index() 704 else: 705 selected_index = -1 706 x = State.get().gl_left 707 for item in State.get().top_menu.left: 708 item.update_size_left() 709 item.x = x 710 item.y = 1080 - TOP_HEIGHT 711 item.h = TOP_HEIGHT 712 x += item.w 713 714 index = len(State.get().top_menu.left) - 1 715 for item in reversed(State.get().top_menu.left): 716 item.render_top_left(selected=(index == selected_index)) 717 index -= 1 718 719 index = len(State.get().top_menu) - 1 720 x = State.get().gl_right 721 for item in reversed(State.get().top_menu.right): 722 item.update_size_right() 723 x -= item.w 724 item.x = x 725 item.y = 1080 - TOP_HEIGHT 726 item.h = TOP_HEIGHT 727 if Mouse.focus: 728 selected = Mouse.focus == item 729 else: 730 selected = index == selected_index 731 item.render_top_right(selected=selected) 732 Mouse.items.append(item) 733 index -= 1 734 gl.glPopMatrix() 735 736 737def render_config_menu(): 738 if not State.get().config_menu: 739 return 740 741 Render.get().ortho_perspective() 742 config_menu = State.get().config_menu 743 # text = config_menu.items[config_menu.index] 744 # otw, th = Render.get().text(text, title_font, 745 # -1.0, -0.93, 2.0, color=(1.0, 1.0, 1.0, 0.36 * strength)) 746 # x = 0.0 + otw / 2 + CONFIG_SEPARATION 747 # for i in range(config_menu.index + 1, len(config_menu.items)): 748 # text = config_menu.items[i] 749 # tw, th = Render.get().text(text, title_font, 750 # x, -0.93, color=(1.0, 1.0, 1.0, 0.36 * strength)) 751 # x += tw + CONFIG_SEPARATION 752 # x = 0.0 - otw / 2 - CONFIG_SEPARATION 753 x = -0.55 754 y = 0.8 755 for i in range(len(config_menu.items)): 756 text = config_menu.items[i].upper() 757 # tw, th = Render.get().measure_text(text, title_font) 758 # x -= tw + CONFIG_SEPARATION 759 y -= 0.15 760 if i == config_menu.index and config_menu == State.get().navigatable: 761 color = (1.0, 1.0, 1.0, 1.0) 762 else: 763 color = (1.0, 1.0, 1.0, 0.33) 764 Render.get().text(text, Font.subtitle_font, x, y, color=color) 765 766 767def render_scanning_status(): 768 # Render.get().hd_perspective() 769 # text = GameScanner.get_status() 770 # Render.get().dirty = True 771 # 772 # fs_emu_texturing(False) 773 # 774 # z = 0.0 775 # 776 # glBegin(GL_QUADS) 777 # glColor3f(0.0, 0.0, 0.0) 778 # glVertex3f( 0, 500, z) 779 # glVertex3f(1920, 500, z) 780 # glVertex3f(1920, 700, z) 781 # glVertex3f( 0, 700, z) 782 # glEnd() 783 # 784 # Render.get().text(text, Font.title_font, 200, 600, color=(1.0, 1.0, 785 # 1.0, 1.0)) 786 # 787 # glBegin(GL_QUADS) 788 # glColor3f(1.0, 1.0, 1.0) 789 # x = 200 790 # y = 500 791 # z = 0.9 792 # x2 = 200 + 1520 * GameScanner.progress 793 # glVertex3f(x, y, z) 794 # glVertex3f(x2, y, z) 795 # glVertex3f(x2, y + 20, z) 796 # glVertex3f(x, y + 20, z) 797 # glEnd() 798 # fs_emu_texturing(True) 799 pass 800 801 802def do_render(): 803 if current_menu is None: 804 return 805 806 current_menu.update() 807 808 if RunTransition.value > 0.99: 809 # do not render anything when running a game 810 return 811 812 if State.get().currently_ingame: 813 # print("currently ingame") 814 return 815 816 # try to exploit parallelism by uploading texture while rendering 817 TextureManager.get().load_textures(1) 818 819 # clear mouseover rects -these will be calculated during rendering 820 Mouse.items[:] = [] 821 Render.get().standard_perspective() 822 823 # scanning = GameScanner.scanning 824 825 data = current_menu.render() 826 current_menu.render_transparent(data) 827 828 # if GameScanner.is_scanning(): 829 if False: 830 render_scanning_status() 831 State.get().was_scanning = True 832 else: 833 render_config_menu() 834 if State.get().was_scanning: 835 print("State.get().was_scanning") 836 State.get().was_scanning = False 837 # reload current menu 838 839 # if current_menu.parent_menu: 840 # result = current_menu.parent_menu.selected_item.activate( 841 # current_menu.parent_menu) 842 # if isinstance(result, Menu): 843 # #if len(result) == 0: 844 # # result.append(NoItem()) 845 # result.parent_menu = current_menu.parent_menu 846 # print("set new menu (rescanned games)") 847 # set_current_menu(result) 848 recreate_main_menu_if_necessary() 849 850 render_top() 851 852 if State.get().dialog: 853 State.get().dialog.render() 854 855 render_global_fade() 856 NotificationRender.render() 857 if RunTransition.value > 0.0: 858 render_fade(a=RunTransition.value) 859 860 861def render_fade(r=0.0, g=0.0, b=0.0, a=0.0): 862 Render.get().hd_perspective() 863 fs_emu_blending(True) 864 fs_emu_texturing(False) 865 gl.glBegin(gl.GL_QUADS) 866 gl.glColor4f(r * a, g * a, b * a, a) 867 gl.glVertex2f(0, 0) 868 gl.glVertex2f(1920, 0) 869 gl.glVertex2f(1920, 1080) 870 gl.glVertex2f(0, 1080) 871 gl.glEnd() 872 873 874def render_global_fade(): 875 t = State.get().time 876 if State.get().fade_end >= t >= State.get().fade_start: 877 a = (t - State.get().fade_start) / ( 878 State.get().fade_end - State.get().fade_start 879 ) 880 if a < 0.0: 881 a = 0.0 882 elif a > 1.0: 883 a = 1.0 884 885 Render.get().hd_perspective() 886 gl.glPushMatrix() 887 gl.glTranslatef(0.0, 0.0, 0.99999) 888 fs_emu_blending(True) 889 fs_emu_texturing(True) 890 if State.get().fade_splash: 891 Texture.splash.render( 892 (1920 - Texture.splash.w) // 2, 893 (1080 - Texture.splash.h) // 2, 894 Texture.splash.w, 895 Texture.splash.h, 896 opacity=(1.0 - a), 897 ) 898 899 c = [0, 0, 0, (1.0 - a)] 900 # for i in range(4): 901 # c[i] = State.get().fade_from[i] + \ 902 # (State.get().fade_to[i] - State.get().fade_from[i]) * a 903 # * (a) 904 render_fade(*c) 905 gl.glPopMatrix() 906 Render.get().dirty = True 907 908 909FPS_FRAMES = 100 910render_times = deque() 911for _ in range(FPS_FRAMES): 912 render_times.append(0) 913 914fps_str = "" 915debug_x = 0 916debug_x_2 = 0 917 918 919def render_debug_square(): 920 global debug_x 921 Render.get().hd_perspective() 922 fs_emu_texturing(False) 923 gl.glBegin(gl.GL_QUADS) 924 gl.glColor3f(1.0, 1.0, 1.0) 925 x = debug_x 926 debug_x += 1 927 if debug_x >= 1920: 928 debug_x = 0 929 y = 989 930 z = 0.99 931 gl.glVertex3f(x, y, z) 932 gl.glVertex3f(x + 20, y, z) 933 gl.glVertex3f(x + 20, y + 20, z) 934 gl.glVertex3f(x, y + 20, z) 935 gl.glEnd() 936 fs_emu_texturing(True) 937 938 939def render_debug_square_2(): 940 global debug_x_2 941 Render.get().hd_perspective() 942 fs_emu_texturing(False) 943 gl.glBegin(gl.GL_QUADS) 944 gl.glColor3f(0.2, 0.2, 0.2) 945 x = debug_x_2 946 debug_x_2 += 1 947 if debug_x_2 >= 1920: 948 debug_x_2 = 0 949 y = 989 + 5 950 z = 0.99 951 gl.glVertex3f(x, y, z) 952 gl.glVertex3f(x + 20, y, z) 953 gl.glVertex3f(x + 20, y + 10, z) 954 gl.glVertex3f(x, y + 10, z) 955 gl.glEnd() 956 fs_emu_texturing(True) 957 958 959# FIXME: remove / move some code away 960def swap_buffers(): 961 # global fps_str 962 # 963 # Render.get().ortho_perspective() 964 # #glPushMatrix() 965 # #glTranslatef(0.0, 0.0, 0.5) 966 # 967 # #if not fps_str: 968 # # fps_str = "WHY?" 969 # 970 # if Render.get().display_fps or True: 971 # if fps_str: 972 # Render.get().text(fps_str, Font.main_path_font, 973 # -1.74, 0.82, h=0.1, color=(0.25, 0.25, 0.25, 1.0)) 974 # #glPopMatrix() 975 # 976 # # FIXME: Why does not minimize from fullscreen work on ATI unless we 977 # render 978 # # something here? 979 # glBindTexture(GL_TEXTURE_2D, 0) 980 # glPushMatrix() 981 # glTranslate(2000.0, 0.0, 0.0) 982 # glBegin(GL_QUADS) 983 # glVertex2f(0.0, 0.0) 984 # glVertex2f(1.0, 0.0) 985 # glVertex2f(1.0, 1.0) 986 # glVertex2f(0.0, 1.0) 987 # glEnd() 988 # glPopMatrix() 989 # 990 # #fs_emu_blending(False) 991 # #glEnable(GL_DEPTH_TEST) 992 # 993 # #if Render.get().display_sync: 994 # # glFinish() 995 # 996 # #pygame.display.flip() 997 # print("FIXME: not flipping") 998 # 999 # if Render.get().display_sync: 1000 # # give up time slice 1001 # time.sleep(0.001) 1002 # glFinish() 1003 # 1004 # if Render.get().display_fps: 1005 # t = get_current_time() 1006 # render_times.append(t) 1007 # t0 = render_times.popleft() 1008 # if t0 > 0 and State.get().frame_number % 5 == 0: 1009 # time_diff = t - t0 1010 # #print("{0:0.2f}".format(300.0 / time_diff)) 1011 # fps = FPS_FRAMES / time_diff 1012 # if fps >= 100: 1013 # fps_str = "FPS: {0:0.0f}".format(fps) 1014 # else: 1015 # fps_str = "FPS: {0:0.1f}".format(fps) 1016 # #Render.get().text(fps_str, Font.title_font, 1017 # # -1.0, 0.90, 2.0, shadow=True) 1018 State.get().frame_number += 1 1019 Render.get().delete_textures() 1020 1021 1022def render_screen(): 1023 # set Render.get().dirty to False here, so that render functions can 1024 # request a new render frame by setting dirty 1025 Render.get().dirty = False 1026 # glEnable(GL_SCISSOR_TEST) 1027 # can_idle = 1028 if SDL_IsMinimized(): 1029 time.sleep(0.01) 1030 return 1031 # Render.get().dirty = True 1032 gl.glClearColor(0.0, 0.0, 0.0, 1.0) 1033 gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) 1034 do_render() 1035 if Render.get().display_fps: 1036 Render.get().dirty = True 1037 if RENDER_DEBUG_SQUARES: 1038 render_debug_square() 1039 1040 1041# noinspection PyPep8Naming 1042def init_display(): 1043 global display 1044 global real_display_height # , display_yoffset 1045 1046 # global banner_texture, shadow_texture, gloss_texture 1047 # global top_texture, top_logo_texture, logo_texture 1048 # global missing_cover_texture, default_item_texture 1049 # global backdrop_texture 1050 1051 logger.debug("Init OpenGL menu display") 1052 1053 DisplayLists.clear() 1054 1055 # on_resize() 1056 # depth = 0 1057 # FIXME: HACK / TESTING 1058 # if not Settings.fullscreen_menu: 1059 # if windows: 1060 # os.environ["SDL_VIDEO_WINDOW_POS"] = "3,29" 1061 # else: 1062 # os.environ["SDL_VIDEO_WINDOW_POS"] = "0,0" 1063 # maximize_window = (not Settings.fullscreen_menu and 1064 # Settings.windowed_size is None) 1065 1066 # display_info = pygame.display.Info() 1067 # dw = display_info.current_w 1068 # dh = display_info.current_h 1069 # dw, dh = fsui.get_screen_size() 1070 # dw, dh = 100, 100 1071 Render.get().display_width = main_window.width 1072 Render.get().display_height = main_window.height 1073 1074 # if Settings.fullscreen_menu: 1075 # print("fullscreen is True") 1076 # if windows: 1077 # #resolution = (0, 0) 1078 # #flags = pygame.OPENGL | pygame.DOUBLEBUF | pygame.NOFRAME \ 1079 # # | pygame.FULLSCREEN 1080 # os.environ["SDL_VIDEO_WINDOW_POS"] = "0,0" 1081 # flags = pygame.OPENGL | pygame.DOUBLEBUF | pygame.NOFRAME 1082 # #flags = flags | pygame.FULLSCREEN 1083 # #if fs.linux: 1084 # # pass 1085 # #else: 1086 # if dw > dh * 2: 1087 # # Assume dual monitor setup - hack for Linux / SDL 1088 # resolution = (dw / 2, dh) 1089 # else: 1090 # resolution = (dw, dh) 1091 # else: # fullscreen, but not microsoft windows 1092 # #resolution = (0, 0) 1093 # flags = pygame.OPENGL | pygame.DOUBLEBUF | pygame.NOFRAME #| 1094 # pygame.FULLSCREEN 1095 # if dw > dh * 2: 1096 # # Assume dual monitor setup - hack for Linux / SDL 1097 # resolution = (dw / 2, dh) 1098 # else: 1099 # resolution = (dw, dh) 1100 # if linux: 1101 # overscan = Config.get("display/overscan", "0,0,0,0") 1102 # try: 1103 # overscan = overscan.split(",") 1104 # overscan = [int(x.strip()) for x in overscan] 1105 # print("using overscan", overscan) 1106 # except Exception as e: 1107 # print("error parsing overscan from config:", repr(e)) 1108 # overscan = [0, 0, 0, 0] 1109 # os.environ["SDL_VIDEO_WINDOW_POS"] = "{0},{1}".format( 1110 # overscan[0], overscan[1]) 1111 # resolution = (resolution[0] - overscan[0] - overscan[2], 1112 # resolution[1] - overscan[1] - overscan[3]) 1113 # elif macosx: 1114 # # FIXME: fullscreen mode does not work very well. -When 1115 # # opening a fullscreen emulator from fullscreen, the emulator 1116 # # crashes on glViewport. Tested with fs-amiga. 1117 # #flags |= pygame.FULLSCREEN 1118 # 1119 # # for now, we create an almost maximized window, works 1120 # # quite well when the dock is set to auto-hide 1121 # #resolution = (resolution[0], resolution[1] - 22) 1122 # 1123 # # FIXME: trying LSUIPresentationMode 1124 # os.environ["SDL_VIDEO_WINDOW_POS"] = "0,0" 1125 # 1126 # # kUIModeNormal = 0 1127 # # kUIModeContentSuppressed = 1 1128 # # kUIModeContentHidden = 2 1129 # # kUIModeAllSuppressed = 4 1130 # kUIModeAllHidden = 3 1131 # kUIOptionAutoShowMenuBar = 1 << 0 1132 # # kUIOptionDisableAppleMenu = 1 << 2 1133 # # kUIOptionDisableProcessSwitch = 1 << 3 1134 # # kUIOptionDisableForceQuit = 1 << 4 1135 # # kUIOptionDisableSessionTerminate = 1 << 5 1136 # # kUIOptionDisableHide = 1 << 6 1137 # 1138 # #noinspection PyUnresolvedReferences 1139 # import objc 1140 # #noinspection PyUnresolvedReferences 1141 # from Foundation import NSBundle 1142 # bundle = NSBundle.bundleWithPath_( 1143 # "/System/Library/Frameworks/Carbon.framework") 1144 # objc.loadBundleFunctions( 1145 # bundle, globals(), 1146 # ((str("SetSystemUIMode"), str("III"), str("")),)) 1147 # #noinspection PyUnresolvedReferences 1148 # SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar) 1149 # 1150 # else: 1151 # if windows and maximize_window and \ 1152 # not Settings.window_decorations: 1153 # import ctypes 1154 # SPI_GETWORKAREA = 48 1155 # 1156 # class RECT(ctypes.Structure): 1157 # _fields_ = [ 1158 # ("left", ctypes.c_ulong), 1159 # ("top", ctypes.c_ulong), 1160 # ("right", ctypes.c_ulong), 1161 # ("bottom", ctypes.c_ulong)] 1162 # 1163 # m = ctypes.windll.user32 1164 # r = RECT() 1165 # m.SystemParametersInfoA(SPI_GETWORKAREA, 0, ctypes.byref(r), 0) 1166 # x = int(r.left) 1167 # y = int(r.top) 1168 # w = int(r.right) - int(r.left) 1169 # h = int(r.bottom) - int(r.top) 1170 # print(x, y, w, h) 1171 # WINDOWED_SIZE[0] = w 1172 # WINDOWED_SIZE[1] = h 1173 # os.environ["SDL_VIDEO_WINDOW_POS"] = "{0},{1}".format(x, y) 1174 # State.get().allow_minimize = False 1175 # 1176 # if Settings.windowed_size: 1177 # print("Settings.windowed_size", Settings.windowed_size) 1178 # WINDOWED_SIZE[0] = Settings.windowed_size[0] 1179 # WINDOWED_SIZE[1] = Settings.windowed_size[1] 1180 # Render.get().display_width = WINDOWED_SIZE[0] 1181 # Render.get().display_height = WINDOWED_SIZE[1] 1182 # #if dw > 1400: 1183 # # Render.get().display_width = 1280 1184 # # Render.get().display_height = 720 1185 # else: 1186 # Render.get().display_width = WINDOWED_SIZE[0] 1187 # Render.get().display_height = WINDOWED_SIZE[1] 1188 # resolution = (Render.get().display_width, Render.get().display_height) 1189 # #print(resolution) 1190 # #sys.exit(1) 1191 # if Settings.window_decorations: 1192 # flags = pygame.OPENGL | pygame.DOUBLEBUF | pygame.RESIZABLE 1193 # else: 1194 # flags = pygame.OPENGL | pygame.DOUBLEBUF | pygame.NOFRAME 1195 # 1196 # display_yoffset = 0 1197 # Mouse.set_visible(False) 1198 # 1199 # pygame.display.gl_set_attribute(pygame.GL_STENCIL_SIZE, 8) 1200 # pygame.display.gl_set_attribute(pygame.GL_DEPTH_SIZE, 16) 1201 # 1202 # Render.get().display_sync = ENABLE_VSYNC 1203 # if Render.get().display_sync: 1204 # print("enabling vertical sync") 1205 # os.environ["__GL_SYNC_TO_VBLANK"] = "1" 1206 # pygame.display.gl_set_attribute(pygame.GL_SWAP_CONTROL, 1) 1207 # else: 1208 # os.environ["__GL_SYNC_TO_VBLANK"] = "0" 1209 # pygame.display.gl_set_attribute(pygame.GL_SWAP_CONTROL, 0) 1210 # pygame.display.gl_set_attribute(pygame.GL_DOUBLEBUFFER, 1) 1211 # fsaa = Config.get_int("video/fsaa", 0) 1212 # if fsaa: 1213 # pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLEBUFFERS, 1) 1214 # pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLESAMPLES, fsaa) 1215 # print("pygame set display mode", resolution, flags, depth) 1216 # display = pygame.display.set_mode(resolution, flags, depth) 1217 # if not Settings.fullscreen_game: 1218 # try: 1219 # del os.environ["SDL_VIDEO_WINDOW_POS"] 1220 # except KeyError: 1221 # pass 1222 # 1223 # if app.name == "fs-uae-arcade": 1224 # pygame.display.set_caption("FS-UAE Arcade") 1225 # else: 1226 # pygame.display.set_caption("FS Game Center") 1227 # 1228 # # FIXME: DISABLING MAXIMIZE FOR DEBUGGING 1229 # #maximize_window = False 1230 # if maximize_window: 1231 # print("maximizing window") 1232 # SDL_Maximize() 1233 # for event in pygame.event.get(): 1234 # if event.type == pygame.VIDEORESIZE: 1235 # #WINDOWED_SIZE[0] = event.w 1236 # #WINDOWED_SIZE[1] = event.h 1237 # on_resize((event.w, event.h)) 1238 # print("DISPLAY.GET_SIZE", display.get_size()) 1239 # else: 1240 # on_resize(display.get_size()) 1241 1242 gl.glMatrixMode(gl.GL_MODELVIEW) 1243 1244 gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA) 1245 gl.glClearColor(*State.get().fade_from) 1246 1247 fs_emu_texturing(True) 1248 Texture.splash = Texture("splash.png") 1249 1250 for _ in range(0): 1251 gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) 1252 # gl.glClear(gl.GL_COLOR_BUFFER_BIT) 1253 Render.get().hd_perspective() 1254 Texture.splash.render( 1255 (1920 - Texture.splash.w) // 2, 1256 (1080 - Texture.splash.h) // 2, 1257 Texture.splash.w, 1258 Texture.splash.h, 1259 ) 1260 gl.glFinish() 1261 # pygame.display.flip() 1262 gl.glFinish() 1263 1264 gl.glEnable(gl.GL_DEPTH_TEST) 1265 1266 1267def init_textures(): 1268 Texture.shadow = Texture.from_resource("shadow.png") 1269 Texture.shadow2 = Texture.from_resource("shadow2.png") 1270 # Texture.gloss = Texture.from_resource("gloss.png") 1271 Texture.gloss = Texture("gloss.png") 1272 Texture.screen_gloss = Texture("screen_gloss.png") 1273 Texture.static = Texture("preview_static0.png") 1274 Texture.default_item = Texture("default_item.png") 1275 Texture.missing_screenshot = Texture("missing_screenshot.png") 1276 Texture.missing_cover = Texture("missing_cover.png") 1277 # path = os.path.join(fs.get_data_dir(), "logo.png") 1278 # if os.path.exists(path): 1279 # im = Image.open(path) 1280 # Texture.logo = Texture.load(im) 1281 # else: 1282 Texture.logo = Texture.from_resource("logo.png") 1283 Texture.top = Texture.from_resource("top.png") 1284 Texture.top_logo = Texture("top_logo.png") 1285 Texture.top_logo_selected = Texture("top_logo_selected.png") 1286 1287 Texture.add = Texture("add.png") 1288 Texture.add_selected = Texture("add_selected.png") 1289 Texture.home = Texture("home.png") 1290 Texture.home_selected = Texture("home_selected.png") 1291 Texture.minimize = Texture("minimize.png") 1292 Texture.minimize_selected = Texture("minimize_selected.png") 1293 Texture.close = Texture("close.png") 1294 Texture.close_selected = Texture("close_selected.png") 1295 Texture.shutdown = Texture("shutdown.png") 1296 Texture.shutdown_selected = Texture("shutdown_selected.png") 1297 1298 Texture.bottom_bar = Texture("bottom_bar.png") 1299 Texture.screen_border_1 = Texture("screen_border_1.png") 1300 Texture.screen_border_2 = Texture("screen_border_2.png") 1301 Texture.top_background = Texture("top_background.png") 1302 Texture.top_item = Texture("top_item.png") 1303 Texture.top_item_selected = Texture("top_item_selected.png") 1304 Texture.top_item_left = Texture("top_item_left.png") 1305 Texture.top_item_left_selected = Texture("top_item_left_selected.png") 1306 Texture.top_item_right = Texture("top_item_right.png") 1307 Texture.top_item_arrow = Texture("top_item_arrow.png") 1308 Texture.top_item_arrow_selected = Texture("top_item_arrow_selected.png") 1309 1310 Texture.sidebar_background = Texture("sidebar_background.png") 1311 Texture.sidebar_background_shadow = Texture( 1312 "sidebar_background_shadow.png" 1313 ) 1314 Texture.glow_top = Texture("glow_top.png") 1315 Texture.glow_top_left = Texture("glow_top_left.png") 1316 Texture.glow_left = Texture("glow_left.png") 1317 1318 Texture.heading_strip = Texture("heading_strip.png") 1319 Texture.item_background = Texture("item_background.png") 1320 Texture.top_item_background = Texture("top_item_background.png") 1321 Texture.logo_32 = Texture("logo-32.png") 1322 1323 Texture.stretch = Texture("stretch.png") 1324 Texture.aspect = Texture("stretch-aspect.png") 1325 Texture.square_pixels = Texture("stretch-none.png") 1326 1327 # # FIXME: TEMPORARY - FOR TESTING, ONLY 1328 # path = "c:\\git\\fs-game-database\\Backdrops\\ffx.png" 1329 # if os.path.exists(path): 1330 # im = Image.open(path) 1331 # #im = resources.get_resource_image_pil("shadow.png") 1332 # assert im.size == (1024, 1024) 1333 # imdata = im.tostring("raw", "RGB") 1334 # backdrop_texture = Render.get().create_texture() 1335 # glBindTexture(GL_TEXTURE_2D, backdrop_texture) 1336 # glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, im.size[0], im.size[1], 0, 1337 # GL_RGB, GL_UNSIGNED_BYTE, imdata) 1338 # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) 1339 # glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) 1340 # else: 1341 # backdrop_texture = 0 1342 1343 1344def init_lighting(): 1345 gl.glLightModeli(gl.GL_LIGHT_MODEL_LOCAL_VIEWER, gl.GL_TRUE) 1346 gl.glLightModeli(gl.GL_LIGHT_MODEL_TWO_SIDE, gl.GL_FALSE) 1347 gl.glLightModeli( 1348 gl.GL_LIGHT_MODEL_COLOR_CONTROL, gl.GL_SEPARATE_SPECULAR_COLOR 1349 ) 1350 1351 light_position = (0.0, 0.0, 3.0, 1.0) 1352 gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, light_position) 1353 gl.glLightfv(gl.GL_LIGHT0, gl.GL_DIFFUSE, (1.0, 1.0, 1.0, 1.0)) 1354 gl.glLightfv(gl.GL_LIGHT0, gl.GL_SPECULAR, (0.0, 0.0, 0.0, 1.0)) 1355 gl.glEnable(gl.GL_LIGHT0) 1356 1357 gl.glLightfv(gl.GL_LIGHT1, gl.GL_DIFFUSE, (0.0, 0.0, 0.0, 1.0)) 1358 gl.glLightfv(gl.GL_LIGHT1, gl.GL_SPECULAR, (1.0, 1.0, 1.0, 1.0)) 1359 gl.glEnable(gl.GL_LIGHT1) 1360 1361 gl.glLightfv(gl.GL_LIGHT2, gl.GL_DIFFUSE, (0.0, 0.0, 0.0, 1.0)) 1362 gl.glLightfv(gl.GL_LIGHT2, gl.GL_SPECULAR, (0.5, 0.5, 0.5, 1.0)) 1363 gl.glEnable(gl.GL_LIGHT2) 1364 1365 gl.glMaterialfv(gl.GL_FRONT, gl.GL_AMBIENT, (0.1, 0.1, 0.1, 1.0)) 1366 gl.glMaterialfv(gl.GL_FRONT, gl.GL_SHININESS, (10,)) 1367 1368 1369def handle_videoresize_event(event): 1370 WINDOWED_SIZE[0] = event.w 1371 WINDOWED_SIZE[1] = event.h 1372 on_resize((event.w, event.h)) 1373 1374 1375def on_resize(display_size): 1376 print("glui.window.on_resize", display_size) 1377 # traceback.print_stack() 1378 1379 global display 1380 global real_display_height, display_yoffset 1381 global browse_curve, header_curve # ,screenshot_curve 1382 1383 DisplayLists.clear() 1384 1385 Render.get().display_width, Render.get().display_height = display_size # 1386 # display# .get_size() 1387 State.get().display_aspect = ( 1388 Render.get().display_width / Render.get().display_height 1389 ) 1390 print(WINDOWED_SIZE) 1391 Settings.windowed_size = tuple(WINDOWED_SIZE) 1392 1393 real_display_height = Render.get().display_height 1394 # if Render.get().display_width / Render.get().display_height < 4 / 3: 1395 # Render.get().display_height = int(Render.get().display_width / 4 * 3) 1396 # display_yoffset = (real_display_height - Render.get( 1397 # ).display_height) // 2 1398 # else: 1399 display_yoffset = 0 1400 # glViewport(0, 0, Render.get().display_width, real_display_height) 1401 # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 1402 # swap_buffers() 1403 # glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 1404 # swap_buffers() 1405 print(display_yoffset) 1406 1407 reinit_fonts() 1408 1409 print( 1410 0, 1411 display_yoffset, 1412 Render.get().display_width, 1413 Render.get().display_height, 1414 ) 1415 gl.glViewport( 1416 0, 1417 display_yoffset, 1418 Render.get().display_width, 1419 Render.get().display_height, 1420 ) 1421 1422 # aspect_ratio = max(4 / 3, (Render.get().display_width / Render.get( 1423 # ).display_height)) 1424 factor = (Render.get().display_width / Render.get().display_height) / ( 1425 1024 / 600 1426 ) 1427 browse_curve = Bezier.bezier( 1428 (-5.0 * factor, -10.0), 1429 (-1.7 * factor, -0.0), 1430 (1.7 * factor, -0.0), 1431 (5.0 * factor, -10.0), 1432 ) 1433 header_curve = Bezier.bezier( 1434 (-2.0 * factor, 0.00), 1435 (-1.0 * factor, 0.075), 1436 (1.0 * factor, 0.075), 1437 (2.0 * factor, 0.00), 1438 steps=50, 1439 ) 1440 1441 # if USE_MENU_TRANSITIONS: 1442 # State.get().fbo = FrameBufferObject( 1443 # Render.get().display_width, Render.get().display_height) 1444 Render.get().dirty = True 1445 1446 1447class LogoStrength(object): 1448 anim = None 1449 value = 1.0 1450 1451 1452def set_ingame_status(): 1453 # State.get().fade_start = State.get().time 1454 # State.get().fade_end = State.get().time + 86400.0 * 365.0 1455 # State.get().fade_from = (0.0, 0.0, 0.0, 0.0) 1456 # State.get().fade_to = (0.0, 0.0, 0.0, 0.0) 1457 # State.get().fade_splash = False 1458 print("State.get().currently_ingame = True") 1459 State.get().currently_ingame = True 1460 1461 1462def back_to_menu_from_game(): 1463 print("State.get().currently_ingame = False") 1464 State.get().currently_ingame = False 1465 1466 set_items_brightness(0.66, duration=0.500) 1467 1468 RunTransition.value = 0.0 1469 RunTransition.anim = None 1470 LogoStrength.anim = None 1471 LogoStrength.value = 1.0 1472 1473 Render.get().zoom = 1.0 1474 Render.get().offset_x = 0.0 1475 Render.get().offset_y = 0.0 1476 1477 State.get().fade_splash = True 1478 State.get().fade_start = State.get().time 1479 State.get().fade_end = State.get().time + 0.5 1480 State.get().fade_from = (0.0, 0.0, 0.0, 2.0) 1481 State.get().fade_to = (0.0, 0.0, 0.0, 0.0) 1482 1483 1484def fade_quit(): 1485 print("fade_quit") 1486 duration = 0.500 1487 alpha = 0.0 1488 start = get_current_time() 1489 while True: 1490 alpha = min(1.0, (get_current_time() - start) / duration) 1491 1492 def render_func(): 1493 render_screen() 1494 Render.get().ortho_perspective() 1495 fs_emu_blending(True) 1496 fs_emu_texturing(False) 1497 gl.glDisable(gl.GL_DEPTH_TEST) 1498 gl.glBegin(gl.GL_QUADS) 1499 gl.glColor4f(0.0, 0.0, 0.0, alpha) 1500 gl.glVertex2f(-10.0, -1.0) 1501 gl.glVertex2f(10.0, -1.0) 1502 gl.glVertex2f(10.0, 1.0) 1503 gl.glVertex2f(-10.0, 1.0) 1504 gl.glEnd() 1505 gl.glEnable(gl.GL_DEPTH_TEST) 1506 # fs_emu_blending(False) 1507 fs_emu_texturing(True) 1508 swap_buffers() 1509 Render.get().dirty = True 1510 1511 Render.get().dirty = True 1512 main_loop_iteration(input_func=None, render_func=render_func) 1513 if alpha >= 1.0: 1514 break 1515 1516 1517def default_render_func(): 1518 # rendered = False 1519 1520 time_str = time.strftime("%H:%M") 1521 if time_str != Render.get().last_time_str: 1522 # clock must be updated, at least 1523 Render.get().dirty = True 1524 Render.get().last_time_str = time_str 1525 1526 if Render.get().dirty or ALWAYS_RENDER: 1527 # print(Render.get().frame_number) 1528 render_screen() 1529 # rendered = True 1530 Render.get().twice = False 1531 # Render.get().twice = True 1532 else: 1533 if not Render.get().twice: 1534 Render.get().twice = True 1535 render_screen() 1536 # rendered = True 1537 if RENDER_DEBUG_SQUARES: 1538 render_debug_square_2() 1539 # if not rendered: 1540 # pass 1541 # time.sleep(0.01) 1542 swap_buffers() 1543 1544 1545def find_item_at_coordinate(pos): 1546 menu = current_menu 1547 # Just checking top items for now 1548 for item in menu.top.left: 1549 if ( 1550 item.x <= pos[0] <= item.x + item.w 1551 and item.y <= pos[1] <= item.y + item.h 1552 ): 1553 return item 1554 for item in menu.top.right: 1555 if ( 1556 item.x <= pos[0] <= item.x + item.w 1557 and item.y <= pos[1] <= item.y + item.h 1558 ): 1559 return item 1560 return None 1561 1562 1563def handle_mouse_event(event): 1564 if event["type"] == "mouse-motion": 1565 item = find_item_at_coordinate(event["pos"]) 1566 # print("mouse over item", item) 1567 state = State.get() 1568 state.mouse_item = item 1569 elif event["type"] == "mouse-press": 1570 item = find_item_at_coordinate(event["pos"]) 1571 state = State.get() 1572 state.mouse_press_item = item 1573 elif event["type"] == "mouse-release": 1574 item = find_item_at_coordinate(event["pos"]) 1575 state = State.get() 1576 # state.mouse_press_item = item 1577 if item is not None and item == state.mouse_press_item: 1578 item.activate(current_menu) 1579 state.mouse_press_item = None 1580 1581 1582def main_loop_iteration( 1583 input_func=default_input_func, render_func=default_render_func 1584): 1585 state = State.get() 1586 1587 # if State.get().currently_ingame: 1588 # print("currently ingame") 1589 # #return False 1590 1591 # print("main loop iteration") 1592 # time.sleep(0.1) 1593 # stop_loop = False 1594 1595 # if State.get().idle_from and State.get().idle_from < get_current_time(): 1596 # #print(State.get().idle_from) 1597 # if not Render.get().dirty: 1598 # #print("waiting for events...") 1599 # events = [pygame.event.wait()] 1600 # else: 1601 # events = pygame.event.get() 1602 # else: 1603 # events = pygame.event.get() 1604 1605 state.time = get_current_time() 1606 1607 # Main.process() 1608 1609 # t = State.get().time 1610 1611 # if len(char_buffer) > 2 and t - char_buffer_last_updated > 0.5: 1612 # print(current_menu, isinstance(current_menu, ItemMenu)) 1613 # if isinstance(current_menu, ItemMenu): 1614 # 1615 # # if len(char_buffer) > 2 and t - char_buffer_last_updated > 0.5: 1616 # if len(char_buffer) > 2: 1617 # create_search_results_menu(char_buffer) 1618 # if len(char_buffer) <= 2: 1619 # # collapse search menu 1620 # 1621 # if hasattr(current_menu, "search_text"): 1622 # print("setting current_menu (something with search)") 1623 # set_current_menu(current_menu.parent_menu) 1624 1625 if state.hide_mouse_time and state.time > state.hide_mouse_time: 1626 if Mouse.focus: 1627 # keep cursor visible if mouse has focus 1628 pass 1629 else: 1630 state.hide_mouse_time = 0 1631 Mouse.set_visible(False) 1632 1633 had_mouse_event = False 1634 for event in InputHandler.pop_all_text_events(): 1635 if event["type"] == "text": 1636 # if key was handled as a virtual button, only allow this 1637 # character if already started typing something, or else 1638 # navigating with X-Arcade may start searching for games 1639 if InputHandler.peek_button(): 1640 if len(current_menu.search_text) > 0: 1641 character_press(event["text"]) 1642 # reset InputHandler so that virtual button 1643 # is not processed, since we handled this press 1644 # as a char 1645 InputHandler.get_button() 1646 else: 1647 character_press(event["text"]) 1648 elif event["type"] in ["mouse-motion", "mouse-press", "mouse-release"]: 1649 had_mouse_event = True 1650 handle_mouse_event(event) 1651 else: 1652 print("[WARNING] Unhandled event", event) 1653 1654 AnimationSystem.update() 1655 NotificationRender.update() 1656 1657 # if idle_events_only: 1658 # # do not update State.get().idle_from 1659 # pass 1660 # elif len(events) > 0: 1661 # #print(events) 1662 # if IDLE: 1663 # State.get().idle_from = State.get().time + IDLE 1664 # #print(State.get().idle_from) 1665 1666 if Render.get().dirty or ALWAYS_RENDER: 1667 if Render.get().non_dirty_state: 1668 print("must start rendering again...") 1669 Render.get().non_dirty_state = False 1670 render_func() 1671 else: 1672 # if not Render.get().non_dirty_state: 1673 # print("pause rendering!") 1674 # Render.get().non_dirty_state = True 1675 Render.get().dirty = True 1676 1677 button = InputHandler.get_button() 1678 if button: 1679 print("InputHandler.get_button", button, InputHandler.last_device) 1680 GameCenter.register_user_activity() 1681 if input_func: 1682 input_func(button) 1683 Render.get().dirty = True 1684 if InputHandler.repeat_info: 1685 Render.get().dirty = True 1686 1687 # if IDLE: 1688 if AnimationSystem.is_active(): 1689 # State.get().idle_from = None 1690 Render.get().dirty = True 1691 # elif State.get().idle_from is None: 1692 # State.get().idle_from = State.get().time + IDLE 1693 if not IDLE: 1694 Render.get().dirty = True 1695 # except KeyboardInterrupt: 1696 # print "KeyboardInterrupt" 1697 # return 1698 # return stop_loop 1699 if had_mouse_event: 1700 Render.get().dirty = True 1701 1702 if not Render.get().display_sync: 1703 t = time.time() 1704 diff = t - Render.get().display_last_iteration 1705 # print(diff) 1706 frame_time = 1 / 60.0 1707 if diff < frame_time: 1708 # FIXME: use real refresh rate / frame time 1709 sleep_time = frame_time - diff 1710 time.sleep(sleep_time) 1711 Render.get().display_last_iteration = t 1712 1713 return state.quit 1714