def cardinal(prefix: str) -> None: ig.dummy(45, 1) ig.same_line() binding_button('n64-' + prefix + '^', prefix + '^') binding_button('n64-' + prefix + '<', prefix + '<') ig.same_line() ig.set_cursor_pos((110, ig.get_cursor_pos().y)) binding_button('n64-' + prefix + '>', prefix + '>') ig.dummy(45, 1) ig.same_line() binding_button('n64-' + prefix + 'v', prefix + 'v')
def render(id: str) -> None: nonlocal error if error is not None: message = error.strip() ig.text('Wafel has crashed. Cause:') lines = message.split('\n') ig.input_text_multiline( '##error-msg', message, len(message) + 1, max(map(len, lines)) * 10, (len(lines) + 1) * ig.get_text_line_height() + 6, ) ig.dummy(10, 10) if ig.button('Exit'): log.info('Aborted') sys.exit(1) ig.same_line() if ig.button('Try to save'): if view.ask_save_filename(): view.save() # ig.same_line() # if view is not None and ig.button('Try to continue (mad lads only)'): # view.reload_ui() # error = None return try: if hasattr(model, 'pipeline'): log.timer.get_num_copies = lambda: model.pipeline.num_copies( ) if config.dev_mode else 0 log.timer.get_num_updates = lambda: model.pipeline.num_advances( ) if config.dev_mode else 0 log.timer.begin_frame() ig.try_render(lambda: do_render(id)) except: error = traceback.format_exc() log.error('Caught: ' + error) finally: log.timer.end_frame()
def render_controller_settings(id: str) -> None: ig.push_id(id) begin_binding_form() def cardinal(prefix: str) -> None: ig.dummy(45, 1) ig.same_line() binding_button('n64-' + prefix + '^', prefix + '^') binding_button('n64-' + prefix + '<', prefix + '<') ig.same_line() ig.set_cursor_pos((110, ig.get_cursor_pos().y)) binding_button('n64-' + prefix + '>', prefix + '>') ig.dummy(45, 1) ig.same_line() binding_button('n64-' + prefix + 'v', prefix + 'v') binding_button('n64-A', 'A') binding_button('n64-B', 'B') binding_button('n64-Z', 'Z') ig.dummy(1, 5) binding_button('n64-L', 'L') binding_button('n64-R', 'R') binding_button('n64-S', 'S') ig.dummy(1, 5) cardinal('') ig.dummy(1, 15) cardinal('C') ig.dummy(1, 15) cardinal('D') ig.dummy(200, 1) ig.pop_id()
def render_key_binding_settings(id: str) -> None: ig.push_id(id) begin_binding_form() ig.text('Frame advance:') button_width = 0 binding_button('frame-prev-fast', '-10', button_width) binding_button('frame-prev', '-1', button_width) binding_button('frame-prev-alt', '-1', button_width) binding_button('frame-next', '+1', button_width) binding_button('frame-next-alt', '+1', button_width) binding_button('frame-next-fast', '+10', button_width) ig.dummy(1, 5) ig.text('3D movement:') button_width = 70 binding_button('3d-camera-move-f', 'Forward', button_width) binding_button('3d-camera-move-b', 'Back', button_width) binding_button('3d-camera-move-l', 'Left', button_width) binding_button('3d-camera-move-r', 'Right', button_width) binding_button('3d-camera-move-u', 'Up', button_width) binding_button('3d-camera-move-d', 'Down', button_width) ig.dummy(1, 5) ig.text('Playback:') button_width = 90 binding_button('playback-play', 'Play', button_width) binding_button('playback-rewind', 'Rewind', button_width) binding_button('playback-speed-up', 'Speed up', button_width) binding_button('playback-slow-down', 'Slow down', button_width) ig.text_colored( 'Tip: Use the frame advance keys\nduring playback to change speed\ntemporarily.', 1.0, 1.0, 1.0, 0.5, ) ig.dummy(200, 1) ig.pop_id()
def render_frame_log_tab(self) -> None: frame_offset = use_state('frame-offset', 1) round_numbers = use_state('round-numbers', True) ig.push_item_width(210) _, frame_offset.value = ig.combo( '##frame-offset', frame_offset.value, ['previous -> current frame', 'current -> next frame'], ) ig.pop_item_width() _, round_numbers.value = ig.checkbox('Round##round-numbers', round_numbers.value) ig.dummy(1, 10) events = self.model.pipeline.frame_log(self.model.selected_frame + frame_offset.value) def string(addr: object) -> str: return self.model.pipeline.read_string(0, dcast(Address, addr)).decode('utf-8') def f32(number: object) -> str: assert isinstance(number, float) if round_numbers.value: return '%.3f' % number else: return str(number) def vec3f(vector: object) -> str: return '(' + ', '.join(map(f32, dcast(list, vector))) + ')' def action(action: object) -> str: return self.model.action_names[dcast(int, action)] indent = 0 action_indent = 0 def show_text(text: str) -> None: ig.text(' ' * indent + text) for event in events: if event['type'] == 'FLT_CHANGE_ACTION': show_text( f'change action: {action(event["from"])} -> {action(event["to"])}' ) elif event['type'] == 'FLT_CHANGE_FORWARD_VEL': show_text( f'change f vel: {f32(event["from"])} -> {f32(event["to"])} ({string(event["reason"])})' ) elif event['type'] == 'FLT_WALL_PUSH': show_text( f'wall push: {vec3f(event["from"])} -> {vec3f(event["to"])} (surface {event["surface"]})' ) elif event['type'] == 'FLT_BEGIN_MOVEMENT_STEP': type_ = {1: 'air', 2: 'ground', 3: 'water'}[event['stepType']] show_text(f'{type_} step {event["stepNum"]}:') indent += 1 elif event['type'] == 'FLT_END_MOVEMENT_STEP': indent -= 1 elif event['type'] == 'FLT_EXECUTE_ACTION': indent -= action_indent action_indent = 0 show_text(f'execute action: {action(event["action"])}') indent += 1 action_indent += 1 else: sorted_event = {'type': event['type']} sorted_event.update(sorted(event.items())) show_text(str(sorted_event))
def render_input_tab(self, tab: TabId) -> None: column_sizes = [170, 370, 200] ig.set_next_window_content_size(sum(column_sizes), 0) ig.begin_child('##input', flags=ig.WINDOW_HORIZONTAL_SCROLLING_BAR) ig.columns(3) for i, w in enumerate(column_sizes): ig.set_column_width(i, w) def render_button(button: str) -> None: self.render_variable( tab, Variable('input-button-' + button).with_frame( self.model.selected_frame), 10, 25, ) ig.dummy(1, 3) render_button('a') ig.same_line() render_button('b') ig.same_line() render_button('z') ig.dummy(1, 5) render_button('s') ig.same_line() ig.dummy(43, 1) ig.same_line() render_button('r') ig.dummy(1, 5) ig.dummy(43, 1) ig.same_line() render_button('cu') ig.dummy(17, 1) ig.same_line() render_button('cl') ig.same_line() render_button('cr') ig.dummy(43, 1) ig.same_line() render_button('cd') ig.next_column() self.render_intended_stick_control('intended') ig.next_column() self.render_stick_control('joystick', tab) ig.columns(1) ig.end_child()
def render_intended_stick_control(self, id: str) -> None: up_options = ['3d view', 'mario yaw', 'stick y', 'world x'] up_option = use_state('up-option', 0) ig.text('up =') ig.same_line() ig.push_item_width(100) _, up_option.value = ig.combo('##up-option', up_option.value, up_options) ig.pop_item_width() ig.dummy(1, 10) 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) face_yaw = dcast( int, self.model.get( Variable('mario-face-yaw').with_frame( self.model.selected_frame))) camera_yaw = dcast( int, self.model.get( Variable('camera-yaw').with_frame(self.model.selected_frame)) or 0) squish_timer = dcast( int, self.model.get(self.model.selected_frame, 'gMarioState->squishTimer')) active_face_yaw = face_yaw events = self.model.pipeline.frame_log(self.model.selected_frame + 1) active_face_yaw_action = None for event in events: if event['type'] == 'FLT_EXECUTE_ACTION': action_name = self.model.action_names[event['action']] active_face_yaw = event['faceAngle'][1] active_face_yaw_action = action_name if action_name == 'idle': break up_angle = { 'mario yaw': active_face_yaw, 'stick y': camera_yaw + 0x8000, 'world x': 0x4000, '3d view': self.model.rotational_camera_yaw, }[up_options[up_option.value]] self.model.input_up_yaw = up_angle raw_stick_x = dcast(int, self.model.get(stick_x_var)) raw_stick_y = dcast(int, self.model.get(stick_y_var)) adjusted = stick_raw_to_adjusted(raw_stick_x, raw_stick_y) intended = stick_adjusted_to_intended( adjusted, face_yaw, camera_yaw, squish_timer != 0, ) def render_value(label: str, value: object, formatter: VariableFormatter) -> Optional[Any]: label_width = 60 value_size = ( 60 if label == 'dyaw' else 80, ig.get_text_line_height() + 2 * ig.get_style().frame_padding[1], ) ig.push_item_width(label_width) ig.selectable(label, width=label_width) ig.pop_item_width() ig.same_line() new_value, _, _ = ui.render_variable_value('value-' + label, value, formatter, value_size) return None if new_value is None else new_value.value target_yaw: Optional[int] = None target_dyaw: Optional[int] = None target_mag: Optional[float] = None target_mag = render_value('int mag', intended.mag, FloatFormatter()) target_yaw = render_value('int yaw', intended.yaw, DecimalIntFormatter()) dyaw = intended.yaw - active_face_yaw target_dyaw = render_value('dyaw', dyaw, DecimalIntFormatter()) ig.same_line() if ig.button('?'): ig.open_popup('active-yaw-expl') if ig.begin_popup('active-yaw-expl'): ig.text(f'{intended.yaw} - {active_face_yaw} = {dyaw}') ig.text(f'intended yaw = {intended.yaw}') if active_face_yaw == face_yaw: ig.text(f'face yaw = {face_yaw}') if active_face_yaw != face_yaw: ig.text( f'face yaw = {active_face_yaw} at start of {active_face_yaw_action} action' ) ig.text(f'(face yaw = {face_yaw} at start of frame)') ig.end_popup() if dyaw not in range(0, 16): if ig.button('dyaw = 0'): target_dyaw = 0 if target_yaw is not None or target_dyaw is not None or target_mag is not None: relative_to = 0 if target_yaw is not None else active_face_yaw if target_dyaw is not None: target_yaw = active_face_yaw + target_dyaw if target_yaw is None: target_yaw = intended.yaw if target_mag is None: target_mag = intended.mag new_raw_stick_x, new_raw_stick_y = intended_to_raw( face_yaw, camera_yaw, squish_timer, target_yaw, target_mag, relative_to) self.model.set(stick_x_var, new_raw_stick_x) self.model.set(stick_y_var, new_raw_stick_y) n_a = intended.yaw - up_angle n_x = intended.mag / 32 * math.sin(-n_a * math.pi / 0x8000) n_y = intended.mag / 32 * math.cos(n_a * math.pi / 0x8000) ig.set_cursor_pos((ig.get_cursor_pos().x + 155, 0)) new_n = ui.render_joystick_control(id, n_x, n_y, 'circle') if new_n is not None: new_n_a = int(math.atan2(-new_n[0], new_n[1]) * 0x8000 / math.pi) new_intended_yaw = up_angle + new_n_a new_intended_mag = 32 * math.sqrt(new_n[0]**2 + new_n[1]**2) new_raw_stick_x, new_raw_stick_y = intended_to_raw( face_yaw, camera_yaw, squish_timer, new_intended_yaw, new_intended_mag, relative_to=0) self.model.set(stick_x_var, new_raw_stick_x) self.model.set(stick_y_var, new_raw_stick_y)