def draw_editor(self): self.editor_surf.fill(EDITOR_BG_COLOR) if self.editor_state == "closed" or self.editing_entity is None: return # NoOp y_pos = self.editor_scroll_amt # render header header_font_size = EDITOR_WIDTH // 8 header_text = self.editing_entity.name header_rect = render_text_centered_x_wrapped( header_text, (0, 0, 0), header_font_size, self.editor_surf, (EDITOR_WIDTH//2, y_pos), EDITOR_WIDTH, padding_top=EDITOR_WIDGET_SPACING, bold=True ) y_pos += header_rect.height # render read-only indicator read_only_indicator_font_height = header_font_size // 2 if not self.edit_mode: # blink red when timing variable is set blink = (self.read_only_indicator_blink_frames // (BLINK_DURATION // 2)) % 2 == 1 color = WARNING_COLOR if blink else (0, 0, 0) self.read_only_indicator_blink_frames = max(self.read_only_indicator_blink_frames - 1, 0) render_text_centered_xy( "(read-only)", color, self.editor_surf, (EDITOR_WIDTH // 2, y_pos + read_only_indicator_font_height // 2 + 4), # pad down just a little extra read_only_indicator_font_height, bold=True ) y_pos += read_only_indicator_font_height # leave space regardless # draw widgets y_pos += EDITOR_WIDGET_SPACING self.widget_rects.clear() for w in self.editing_entity.widgets: h = int(EDITOR_WIDTH / w.aspect_ratio) if w.aspect_ratio else 9999 rect = pg.Rect(0, y_pos, EDITOR_WIDTH, h) real_h = w.draw_onto(self.editor_surf, rect, snapshot_provider=self.snapshot_provider) if real_h: h = real_h rect.height = real_h self.widget_rects.append((rect, w)) y_pos += h + EDITOR_WIDGET_SPACING # TODO: debug this self.editor_content_height = y_pos - self.editor_scroll_amt
def draw_onto(self, surf: pg.Surface, rect: pg.Rect, **kwargs): super().draw_onto(surf, rect) s = rect.width compass_center = round(V2(rect.centerx, rect.centery - s * 0.1)) # pg.draw.circle(surf, (0, 0, 0), tuple(compass_center), round(s * 0.1), width=round(s * 0.05)) # draw_aacircle(surf, *compass_center, round(s * 0.05), (0, 0, 0)) self.hitboxes = [(d, draw_chevron(surf, compass_center + d * s * 0.25, d, (255, 255, 255) if self.get_value() is d else (0, 0, 0), s * 0.12, s * 0.04)) for d in Direction if d is not Direction.NONE] render_text_centered_xy(self.label, (0, 0, 0), surf, V2(rect.centerx, rect.bottom - s * 0.16), FONT_SIZE)
def draw_onto_base(self, surf: pg.Surface, rect: pg.Rect, edit_mode: bool, step_progress: float = 0.0, neighborhood=(([], ) * 5, ) * 5): super().draw_onto_base(surf, rect, edit_mode, step_progress=step_progress, neighborhood=neighborhood) font_size = rect.width * 0.3 text = self.name.split()[0] # gate type render_text_centered_xy(text, GATE_PRIMARY_COLOR, surf, rect.center, font_size, bold=True)
def draw_shelf(self): self.shelf_surf.fill(SHELF_BG_COLOR) # draw palette self.palette_rects.clear() for i, (e_prototype, count) in enumerate(self.level.palette.get_all()): margin = (SHELF_HEIGHT - PALETTE_ITEM_SIZE) // 2 rect = pg.Rect( margin + (PALETTE_ITEM_SIZE + margin + PALETTE_ITEM_SPACING) * i, margin, PALETTE_ITEM_SIZE + 1, PALETTE_ITEM_SIZE + 1 ) self.palette_rects.append((rect, e_prototype)) if count > 0: # only draw item if there are any left (maintains spacing) temp_entity = e_prototype.get_instance() temp_entity.draw_onto(self.shelf_surf, rect, edit_mode=True) # pg.draw.rect(self.shelf_surf, (0, 255, 0), rect) pg.draw.circle(self.shelf_surf, (255, 0, 0), rect.topright, 14) render_text_centered_xy(str(count), (255, 255, 255), self.shelf_surf, rect.topright, 20, bold=True)
def draw_onto_base(self, surf: pg.Surface, rect: pg.Rect, edit_mode: bool, step_progress: float = 0.0, neighborhood=(([], ) * 5, ) * 5): s = rect.width pg.draw.rect(surf, self.color.rgb(), rect) padding = s * 0.35 radius = round(s * 0.2) pg.draw.rect(surf, (255, 255, 255), rect.inflate(-padding, -padding), border_radius=radius) render_text_centered_xy( str(self.count), (0, 0, 0), surf, rect.center, s - padding * 1.75, )
def draw_onto(self, surf: pg.Surface, rect: pg.Rect, snapshot_provider=None) -> None: super().draw_onto(surf, rect) render_text_left_justified( self.label, (0, 0, 0), surf, V2(rect.left + rect.width * 0.03, rect.centery), FONT_SIZE) w = rect.width * 0.45 h = w # rect.height * 0.9 self.snapshot_rect = pg.Rect(rect.left + rect.width * 0.70 - w / 2, rect.top + (rect.height - h) / 2, w, h) # draw background pg.draw.rect(surf, (255, 255, 255), self.snapshot_rect) if self.get_value()[0] is None and not self.in_use: size = FONT_SIZE * 0.65 render_text_centered_xy("not", (63, 63, 63), surf, (self.snapshot_rect.centerx, self.snapshot_rect.centery - size / 2), size) render_text_centered_xy("connected", (63, 63, 63), surf, (self.snapshot_rect.centerx, self.snapshot_rect.centery + size / 2), size) else: if self.in_use: snap = snapshot_provider.take_snapshot_at_mouse( self.snapshot_rect.size) else: snap = snapshot_provider.take_snapshot(self.get_value()[0], self.snapshot_rect.size) surf.blit(snap, self.snapshot_rect) # draw border color = HIGHLIGHT_COLOR if self.in_use else (0, 0, 0) pg.draw.rect(surf, color, self.snapshot_rect, 2)
def draw_onto(self, surf: pg.Surface, rect: pg.Rect, **kwargs): super().draw_onto(surf, rect) self.set_value(clamp(self.get_value(), *self.get_limits())) render_text_left_justified( self.label, (0, 0, 0), surf, V2(rect.left + rect.width * 0.03, rect.centery), FONT_SIZE) # TODO: draw number selector boxes box_width = int(rect.height * 0.75) box_height = int(rect.height * 0.75) box_thickness = 2 self.hitboxes.clear() low, high = self.get_limits() for i, n in enumerate(range(low, high + 1)): # inclusive box = pg.Rect( rect.left + rect.width * 0.375 + (box_width - box_thickness // 2) * i, rect.centery - box_height / 2, box_width, box_height) color = (255, 255, 255) if n == self.get_value() else (0, 0, 0) draw_rectangle(surf, box, (0, 0, 0), thickness=box_thickness) render_text_centered_xy(str(n), color, surf, box.center, FONT_SIZE) self.hitboxes.append((n, box))
def draw_onto_base(self, surf: pg.Surface, rect: pg.Rect, edit_mode: bool, step_progress: float = 0.0, neighborhood=(([], ) * 5, ) * 5): super().draw_onto_base(surf, rect, edit_mode, step_progress=step_progress, neighborhood=neighborhood) m = max(round(rect.width * 0.04), 2) port_width = m * 2 port_height = m lr_pad = rect.width * self.left_right_padding + port_width tb_pad = rect.height * self.top_bottom_padding r = rect.height / 2 - tb_pad # outer outer = pg.Rect( rect.left + lr_pad, rect.top + tb_pad, rect.width - 2 * lr_pad - r, rect.height - 2 * tb_pad, ) pg.draw.circle(surf, GATE_PRIMARY_COLOR, (rect.right - lr_pad - r, rect.centery), r) pg.draw.rect(surf, GATE_PRIMARY_COLOR, outer) # inner inner = outer.inflate(-2 * m, -2 * m) inner.width += m pg.draw.circle(surf, GATE_BG_COLOR, (rect.right - lr_pad - r, rect.centery), r - m) # draw_aacircle( # surf, # int(rect.right - lr_pad - r), int(rect.centery), # int(r - m), # (255, 255, 255) # ) pg.draw.rect(surf, GATE_BG_COLOR, inner) for index in range(self.num_inputs): offset = self.get_port_offset(True, index) pg.draw.rect( surf, GATE_PRIMARY_COLOR, pg.Rect(rect.left + rect.width * offset[0], rect.top + rect.height * offset[1] - port_height / 2, port_width, port_height)) for index in range(self.num_outputs): offset = self.get_port_offset(False, index) pg.draw.rect( surf, GATE_PRIMARY_COLOR, pg.Rect(rect.left + rect.width * offset[0] - (port_width + 1), rect.top + rect.height * offset[1] - port_height / 2, port_width + 1, port_height)) font_size = rect.width * 0.3 render_text_centered_xy("AND", GATE_PRIMARY_COLOR, surf, rect.center, font_size, bold=True)
def draw_onto(self, surf: pg.Surface, rect: pg.Rect, **kwargs) -> None: super().draw_onto(surf, rect, **kwargs) radius = round(rect.height * 0.40) border_width = 2 # draw_width = round(rect.height * 0.075) spacing = radius * 2 + border_width if self.attr is None: minus_visible = True plus_visible = True else: minus_visible = self.get_attr(self.attr) > self.limits[0] plus_visible = self.get_attr(self.attr) < self.limits[1] if not (minus_visible or plus_visible): raise RuntimeError( "at least one of minus/plus buttons must be visible") if minus_visible and plus_visible: minus_center = (rect.centerx - spacing // 2, rect.centery) plus_center = (rect.centerx + spacing // 2, rect.centery) elif minus_visible: minus_center = rect.center elif plus_visible: plus_center = rect.center self.minus_hitbox = pg.Rect(minus_center[0] - radius, minus_center[1] - radius, radius * 2, radius * 2) if minus_visible else None self.plus_hitbox = pg.Rect(plus_center[0] - radius, plus_center[1] - radius, radius * 2, radius * 2) if plus_visible else None background_color = (255, 255, 255) border_color = (0, 0, 0) icon_color = (0, 0, 0) icon_font_size = FONT_SIZE * 1.0 # draw background and border # TODO: antialising!!! combined_rect = rect_union([self.minus_hitbox, self.plus_hitbox]) pg.draw.rect(surf, background_color, combined_rect, border_radius=radius) pg.draw.rect(surf, border_color, combined_rect, width=border_width, border_radius=radius) # draw "-" button if minus_visible: render_text_centered_xy("-", icon_color, surf, self.minus_hitbox.center, icon_font_size) # draw "+" button if plus_visible: render_text_centered_xy("+", icon_color, surf, self.plus_hitbox.center, icon_font_size) # draw divider if minus_visible and plus_visible: pg.draw.line(surf, icon_color, (rect.centerx, rect.centery - radius / 2), (rect.centerx, rect.centery + radius / 2), width=border_width)