Example #1
0
    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)
Example #2
0
    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()
Example #3
0
 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
Example #4
0
  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()
Example #5
0
  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