def __init__(self, model: Model) -> None: global epoch epoch += 1 self.model = model self.show_debug_pane = config.dev_mode self.formatters = DataFormatters(self.model.pipeline) self.formatters[Variable('mario-action')] = EnumFormatter( self.model.action_names) self.frame_sheets: List[FrameSheet] = [ FrameSheet( self.model, self.model, self.model.pipeline, DragHandler(self.model.pipeline), self.model, self.formatters, ), ] for var_name in DEFAULT_FRAME_SHEET_VARS: self.frame_sheets[0].append_variable(Variable(var_name)) self.variable_explorer = VariableExplorer(self.model, self.formatters)
def render_right_column(self) -> None: total_height = ig.get_window_height() if self.show_debug_pane: ig.push_id('debug-pane') ig.begin_child('##pane', height=int(ig.get_window_height() * 0.15)) ig.columns(2) ig.set_column_width(-1, ig.get_window_width() - 300) ig.begin_child('##log') def init_log() -> List[str]: messages = [] log.subscribe(lambda msg: messages.append(str(msg))) return messages messages = use_state_with('messages', init_log).value prev_length = use_state('prev-length', 0) total_height -= ig.get_window_height() if prev_length.value != len(messages): prev_length.value = len(messages) ig.set_scroll_y(ig.get_scroll_max_y() + ig.get_window_height()) for message in messages: ig.text(message) ig.end_child() ig.next_column() for line in log.timer.format(log.timer.get_summaries()): ig.text(line) ig.columns(1) ig.end_child() ig.pop_id() log.timer.begin('fsheet') frame_sheet = self.frame_sheets[0] ig.set_next_window_content_size(frame_sheet.get_content_width(), 0) ig.begin_child( 'Frame Sheet##' + str(epoch) + '-0', height=int(total_height * 0.7), flags=ig.WINDOW_HORIZONTAL_SCROLLING_BAR, ) frame_sheet.render() ig.end_child() if ig.begin_drag_drop_target(): payload = ig.accept_drag_drop_payload('ve-var') if payload is not None: frame_sheet.append_variable(Variable.from_bytes(payload)) ig.end_drag_drop_target() log.timer.end() log.timer.begin('varexp') ig.begin_child('Variable Explorer', border=True) self.variable_explorer.render('variable-explorer') ig.end_child() log.timer.end()
def compute_stick_from_controller(self, cx: float, cy: float) -> Tuple[int, int]: if abs(cx) < 8 / 128: cx = 0 if abs(cy) < 8 / 128: cy = 0 camera_angle = dcast(int, self.model.get(Variable('camera-yaw').with_frame(self.model.selected_frame)) or 0) + 0x8000 up_angle = self.model.input_up_yaw if up_angle is None: up_angle = camera_angle rotation = (up_angle - camera_angle) / 0x8000 * math.pi sx = math.cos(rotation) * cx - math.sin(rotation) * cy sy = math.sin(rotation) * cx + math.cos(rotation) * cy stick_x = min(max(int(sx * 128), -128), 127) stick_y = min(max(int(sy * 128), -128), 127) return stick_x, stick_y
def handle_controller(self) -> None: ig.push_id('controller-inputs') buttons_enabled = use_state('buttons-enabled', False) stick_enabled = use_state('stick-enabled', False) def add_callbacks() -> Ref[bool]: input_edit = Ref(False) def disable_controller(*args, **kwargs) -> None: if not input_edit.value: buttons_enabled.value = False stick_enabled.value = False self.model.on_edit(disable_controller) def frame_change(*args, **kwargs) -> None: if self.model.play_speed == 0.0: disable_controller() self.model.on_selected_frame_change(frame_change) return input_edit input_edit = use_state_with('initialize', add_callbacks).value prev_play_speed = use_state('prev-play-speed', 0.0) if self.model.play_speed != prev_play_speed.value: buttons_enabled.value = False stick_enabled.value = False prev_play_speed.value = self.model.play_speed controller_button_values = { 'input-button-a': input_down('n64-A'), 'input-button-b': input_down('n64-B'), 'input-button-z': input_down('n64-Z'), 'input-button-s': input_down('n64-S'), 'input-button-l': input_down('n64-L'), 'input-button-r': input_down('n64-R'), 'input-button-cu': input_down('n64-C^'), 'input-button-cl': input_down('n64-C<'), 'input-button-cr': input_down('n64-C>'), 'input-button-cd': input_down('n64-Cv'), 'input-button-du': input_down('n64-D^'), 'input-button-dl': input_down('n64-D<'), 'input-button-dr': input_down('n64-D>'), 'input-button-dd': input_down('n64-Dv'), } if any(controller_button_values.values()): buttons_enabled.value = True stick_enabled.value = True for variable_name, new_button_value in controller_button_values.items(): variable = Variable(variable_name).with_frame(self.model.selected_frame) button_value = self.model.get(variable) if buttons_enabled.value and button_value != new_button_value: input_edit.value = True self.model.set(variable, new_button_value) input_edit.value = False controller_stick_values = ( input_float('n64->') - input_float('n64-<'), input_float('n64-^') - input_float('n64-v'), ) # Require a larger magnitude for enabling controller since dead zone may be too small if any(abs(v) > 0.1 for v in controller_stick_values): stick_enabled.value = True buttons_enabled.value = True if stick_enabled.value: stick_x_var = Variable('input-stick-x').with_frame(self.model.selected_frame) stick_y_var = Variable('input-stick-y').with_frame(self.model.selected_frame) new_stick = self.compute_stick_from_controller(*controller_stick_values) stick = (self.model.get(stick_x_var), self.model.get(stick_y_var)) if stick != new_stick: input_edit.value = True self.model.set(stick_x_var, new_stick[0]) self.model.set(stick_y_var, new_stick[1]) input_edit.value = False ig.pop_id()
def render_left_column(self, framebuffer_size: Tuple[int, int]) -> None: total_height = ig.get_window_height() - ig.get_frame_height() # subtract menu bar slider_space = 45 wall_hitbox_radius = use_state('wall-hitbox-radius', 50) wall_hitbox_options = [0, 24, 50, 110] hovered_surface: Ref[Optional[int]] = use_state('hovered-surface', None) new_hovered_surface: Optional[int] = None hidden_surfaces_by_area = \ use_state('hidden-surfaces', cast(Dict[Tuple[int, int], Set[int]], {})).value current_area = ( dcast(int, self.model.get(Variable('level-num').with_frame(self.model.selected_frame))), dcast(int, self.model.get(Variable('area-index').with_frame(self.model.selected_frame))), ) hidden_surfaces = hidden_surfaces_by_area.setdefault(current_area, set()) log.timer.begin('gview1') ig.begin_child( 'Game View 1', height=int(total_height // 2) - slider_space // 2, border=True, ) hovered_surface_1 = ui.render_game_view_rotate( 'game-view-1', framebuffer_size, self.model, wall_hitbox_radius.value, hovered_surface.value, hidden_surfaces, ) ig.set_cursor_pos((10.0, ig.get_window_height() - 30)) ig.text('wall radius') ig.same_line() ig.push_item_width(50) _, index = ig.combo( '##wall-hitbox-radius', wall_hitbox_options.index(wall_hitbox_radius.value), list(map(str, wall_hitbox_options)), ) wall_hitbox_radius.value = wall_hitbox_options[index] ig.pop_item_width() ig.end_child() log.timer.end() log.timer.begin('gview2') ig.begin_child( 'Game View 2', height=int(total_height // 2) - slider_space // 2, border=True, ) hovered_surface_2 = ui.render_game_view_birds_eye( 'game-view-2', framebuffer_size, self.model, wall_hitbox_radius.value, hovered_surface.value, hidden_surfaces, ) ig.end_child() log.timer.end() new_hovered_surface = hovered_surface_1 or hovered_surface_2 if new_hovered_surface is not None and ig.is_mouse_clicked(1): ig.open_popup('surface-ctx') hovered_surface.value = new_hovered_surface if ig.begin_popup('surface-ctx'): if hovered_surface.value is not None: if hovered_surface.value in hidden_surfaces: if ig.menu_item('Show')[0]: hidden_surfaces.remove(hovered_surface.value) else: if ig.menu_item('Hide')[0]: hidden_surfaces.add(hovered_surface.value) if ig.menu_item('Properties')[0]: self.variable_explorer.open_surface_tab(hovered_surface.value) ig.end_popup() else: hovered_surface.value = new_hovered_surface if hovered_surface.value is not None and ig.is_mouse_clicked(2): if hovered_surface.value in hidden_surfaces: hidden_surfaces.remove(hovered_surface.value) else: hidden_surfaces.add(hovered_surface.value) speed_options = [0.05, 0.25, 0.5, 1, 2, 4] saved_play_direction = use_state('saved-play-direction', 0) saved_speed_index = use_state('saved-speed-index', 3) play_direction = saved_play_direction.value speed_index = saved_speed_index.value if play_direction == 0: frame_advance = 0 play_override = 0 def control(name: str, speed: int) -> None: nonlocal frame_advance, play_override x = input_down_gradual(name, 0.25) if x == 1.0: play_override = speed elif input_pressed(name): frame_advance += speed control('frame-next', 1) control('frame-next-alt', 1) control('frame-prev', -1) control('frame-prev-alt', -1) control('frame-next-fast', 10) control('frame-prev-fast', -10) if play_override != 0: if abs(play_override) in speed_options: speed_index = speed_options.index(abs(play_override)) else: speed_index = len(speed_options) - 1 play_direction = 1 if play_override > 0 else -1 else: self.model.selected_frame += frame_advance else: if input_down('frame-next') or input_down('frame-next-alt'): if play_direction == 1: speed_index += 1 else: play_direction = -play_direction elif input_down('frame-prev') or input_down('frame-prev-alt'): if play_direction == -1: speed_index += 1 else: play_direction = -play_direction elif input_down('frame-next-fast'): if play_direction == 1: speed_index += 2 else: play_direction = -play_direction speed_index += 1 elif input_down('frame-prev-fast'): if play_direction == -1: speed_index += 2 else: play_direction = -play_direction speed_index += 1 speed_index = min(max(speed_index, 0), len(speed_options) - 1) self.model.play_speed = play_direction * speed_options[speed_index] self.model.playback_mode = saved_play_direction.value != 0 def play_button(label: str, direction: int) -> None: disabled = play_direction == direction if ig.disableable_button(label, enabled=play_direction != direction): saved_play_direction.value = direction play_button('<|', -1) ig.same_line() play_button('||', 0) ig.same_line() play_button('|>', 1) ig.same_line() ig.push_item_width(63) changed, new_index = ig.combo( '##speed-option', speed_index, [str(s) + 'x' for s in speed_options], ) ig.pop_item_width() if changed: saved_speed_index.value = new_index if input_pressed('playback-play'): if saved_play_direction.value == 0: saved_play_direction.value = 1 else: saved_play_direction.value = 0 if input_pressed('playback-rewind'): if saved_play_direction.value == 0: saved_play_direction.value = -1 else: saved_play_direction.value = 0 if input_pressed('playback-speed-up'): saved_speed_index.value = min(saved_speed_index.value + 1, len(speed_options) - 1) if input_pressed('playback-slow-down'): saved_speed_index.value = max(saved_speed_index.value - 1, 0) ig.same_line() new_frame = ui.render_frame_slider( 'frame-slider', self.model.selected_frame, self.model.max_frame - 1, self.model.pipeline.cached_frames() if self.show_debug_pane else [], ) if new_frame is not None: self.model.selected_frame = new_frame.value