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 render_headers(self) -> None: header_labels = [ self.displayer.column_header(column.variable) for column in self.columns ] header_lines = max((len(label.split('\n')) for label in header_labels), default=1) ig.columns(len(self.columns) + 1) if len(self.columns) > 0: ig.set_column_width(-1, self.frame_column_width) ig.text('') ig.next_column() for index, column in enumerate(self.columns): initial_cursor_pos = ig.get_cursor_pos() ig.selectable( '##fs-col-' + str(id(self)) + '-' + str(id(column)), height=header_lines * ig.get_text_line_height(), ) # TODO: Width adjusting ig.set_column_width(-1, column.width) if ig.begin_drag_drop_source(): ig.text(header_labels[index]) ig.set_drag_drop_payload('fs-col', str(index).encode('utf-8')) ig.end_drag_drop_source() if ig.begin_drag_drop_target(): payload = ig.accept_drag_drop_payload('fs-col') if payload is not None: source = int(payload.decode('utf-8')) self._move_column(source, index) payload = ig.accept_drag_drop_payload('ve-var') if payload is not None: self._insert_variable(index, Variable.from_bytes(payload)) ig.end_drag_drop_target() if ig.is_item_hovered() and ig.is_mouse_clicked(2): self._remove_column(index) if ig.begin_popup_context_item('##fs-colctx-' + str(id(self)) + '-' + str(id(column))): if ig.selectable('Close')[0]: self._remove_column(index) ig.end_popup_context_item() ig.set_cursor_pos(initial_cursor_pos) ig.text(header_labels[index]) ig.next_column() ig.separator() ig.columns(1)
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(self) -> None: ig.push_id(str(epoch)) # if ig.is_key_pressed(ord('`')): # self.show_debug_pane = not self.show_debug_pane self.handle_controller() prev_frame_time = use_state_with('prev-frame-time', time.time) accum_time = use_state('accum-time', 0.0) now = time.time() accum_time.value += now - prev_frame_time.value prev_frame_time.value = now play_speed = self.model.play_speed if play_speed == 0.0: accum_time.value = 0 else: target_fps = 30 * abs(play_speed) target_dt = 1 / target_fps updates = 0 while accum_time.value >= target_dt and updates < 20: accum_time.value -= target_dt self.model.selected_frame += 1 if play_speed > 0 else -1 self.handle_controller() updates += 1 ig_window_size = ig.get_window_size() window_size = (int(ig_window_size.x), int(ig_window_size.y)) ig.columns(2) self.render_left_column(window_size) ig.next_column() self.render_right_column() ig.columns(1) ig.pop_id()
def render_rows(self) -> None: ig.columns(len(self.columns) + 1) min_row = int(ig.get_scroll_y() + self.scroll_delta) // self.row_height - 1 min_row = max(min_row, 0) max_row = int(ig.get_scroll_y() + self.scroll_delta + ig.get_window_height()) // self.row_height # max_row = min(max_row, self.get_row_count() - 1) self.sequence.extend_to_frame(max_row + 100) timeline_operations: List[Callable[[], None]] = [] mouse_pos = ( ig.get_mouse_pos().x - ig.get_window_position().x, ig.get_mouse_pos().y - ig.get_window_position().y + ig.get_scroll_y() + self.scroll_delta, ) for row in range(min_row, max_row + 1): row_pos = (0.0, row * self.row_height - self.scroll_delta) ig.set_cursor_pos(row_pos) mouse_in_row = mouse_pos[1] > row_pos[1] and mouse_pos[ 1] <= row_pos[1] + self.row_height if mouse_in_row and self.dragging and time.time( ) - self.time_started_dragging > 0.1: self.drag_handler.update_drag(row) if len(self.columns) > 0: ig.set_column_width(-1, self.frame_column_width) clicked, _ = ig.selectable( str(row) + '##fs-framenum-' + str(id(self)) + '-' + str(row), row == self.sequence.selected_frame, height=self.row_height - 8, # TODO: Compute padding ) if clicked: self.sequence.set_selected_frame(row) if ig.begin_popup_context_item('##fs-framenumctx-' + str(id(self)) + '-' + str(row)): if ig.selectable('Insert above')[0]: def op(row): return lambda: self.sequence.insert_frame(row) timeline_operations.append(op(row)) if ig.selectable('Insert below')[0]: def op(row): return lambda: self.sequence.insert_frame(row + 1) timeline_operations.append(op(row)) if ig.selectable('Delete')[0]: def op(row): return lambda: self.sequence.delete_frame(row) timeline_operations.append(op(row)) ig.end_popup_context_item() ig.next_column() for column in self.columns: self.render_cell(row, column) ig.set_column_width(-1, column.width) ig.next_column() ig.separator() ig.set_cursor_pos((0, (self.sequence.max_frame + 1) * self.row_height)) ig.columns(1) for operation in timeline_operations: operation()
def render_tabs( id: str, tabs: List[TabInfo], open_tab_index: Optional[int] = None, allow_windowing=False, ) -> Tuple[Optional[int], Optional[int]]: ig.push_id(id) root_id = get_local_state_id_stack() ig.columns(2) closed_tab = None rendered = use_state('rendered', False) if not rendered.value: rendered.value = True ig.set_column_width(-1, 120) if len(tabs) == 0: ig.pop_id() return None, closed_tab selected_tab_index = use_state_with('selected-tab-index', lambda: open_tab_index or 0) selected_tab_id = use_state_with('selected-tab', lambda: tabs[selected_tab_index.value].id) if open_tab_index is not None: selected_tab_index.value = open_tab_index selected_tab_id.value = tabs[open_tab_index].id windowed_tabs = use_state('windowed-tabs', cast(Set[str], set())).value # TODO: Change selected tab if windowed # Handle deletion/insertion if selected_tab_index.value >= len(tabs): selected_tab_index.value = len(tabs) - 1 if tabs[selected_tab_index.value].id != selected_tab_id.value: matching_indices = [ i for i in range(len(tabs)) if tabs[i].id == selected_tab_id.value ] if len(matching_indices) > 0: selected_tab_index.value = matching_indices[0] else: selected_tab_id.value = tabs[selected_tab_index.value].id ig.begin_child('tabs') for i, tab in enumerate(tabs): if tab.id in windowed_tabs: continue _, selected = ig.selectable( tab.label + '##tab-' + tab.id, selected_tab_id.value == tab.id, ) if selected: selected_tab_index.value = i selected_tab_id.value = tab.id if tab.closable and ig.is_item_hovered() and ig.is_mouse_clicked(2): closed_tab = i if allow_windowing or tab.closable: if ig.begin_popup_context_item(f'##ctx-{tab.id}'): if allow_windowing and ig.selectable('Pop out')[0]: windowed_tabs.add(tab.id) if tab.closable and ig.selectable('Close')[0]: closed_tab = i ig.end_popup_context_item() ig.end_child() ig.next_column() ig.begin_child('content', flags=ig.WINDOW_HORIZONTAL_SCROLLING_BAR) tab = tabs[selected_tab_index.value] if tab.id not in windowed_tabs: push_local_state_rebase(('rebase-tabs', ) + root_id) tab.render(tab.id) # type: ignore pop_local_state_rebase() ig.end_child() ig.columns(1) for tab_id in set(windowed_tabs): matching = [tab for tab in tabs if tab.id == tab_id] if len(matching) == 0: windowed_tabs.remove(tab.id) continue tab = matching[0] ig.set_next_window_size(*ig.get_window_size(), ig.ONCE) ig.set_next_window_position(*ig.get_window_position(), ig.ONCE) ig.push_style_color(ig.COLOR_WINDOW_BACKGROUND, 0.06, 0.06, 0.06, 0.94) _, opened = ig.begin( tab.label + '##window-' + tab.id, closable=True, flags=ig.WINDOW_HORIZONTAL_SCROLLING_BAR, ) push_local_state_rebase(('rebase-tabs', ) + root_id) tab.render(tab.id) # type: ignore pop_local_state_rebase() ig.end() ig.pop_style_color() if not opened: windowed_tabs.remove(tab.id) ig.pop_id() return ( None if open_tab_index == selected_tab_index.value else selected_tab_index.value, closed_tab, )