def draw(self, gc): self.deselected = self.context.object_selection for obj in self.context.object_selection: gc.draw_rect(Rect(obj.get_bound_rect()), Color(0, 0, 192), 3) gc.fill_rect(Rect(obj.get_bound_rect()), Color(0, 0, 128, 64), 3) if self.state == ObjMapSelectTool.STATE_DRAG: pass elif self.state == ObjMapSelectTool.STATE_SELECT: gc.draw_rect(Rect(self.selection_rect), Color(255, 255, 255))
def make_rect_object(metadata, color=None): if color is None: color = Colorf(0, 0, 1.0, 0.5) pos = Point(0, 0) size = Size(64, 64) obj = ObjMapRectObject(Rect(pos, size), color, metadata) return obj
def set_bounding_rect(self, rect): if rect != Rect(0, 0, 0, 0): self._has_bounding_rect = True self.bounding_rect = rect else: self._has_bounding_rect = False self.bounding_rect = rect
def draw(self, gc, color=Color(255, 255, 255, 100)): tile_size = self.tilemap.get_tileset().get_tile_size() gc.fill_rect( Rect(self.selection.left * tile_size, self.selection.top * tile_size, self.selection.right * tile_size, self.selection.bottom * tile_size), color)
def get_bound_rect(self): origin_enum, align_x, align_y = self.sprite.get_alignment() align_x = -align_x origin = Origin.calc_origin( origin_enum, Size(self.sprite.width, self.sprite.height)) return Rect( Point(self.pos) - origin - Point(align_x, align_y), Size(self.sprite.width, self.sprite.height))
def load_v2(self, data): self.name = "<No Name>" self.music = "" self.init_script = "" self.gravity = 10.0 self.width = 0 self.height = 0 self.objects = [] self.tilemaps = [] self.object_layer = ObjectLayer() self.editormap = EditorMap() self.editormap.add_layer(self.object_layer) for i in data: (name, data) = i[0], i[1:] if name == "name": self.name = data[0] elif name == "ambient-light": self.ambient_light = data elif name == "gravity": self.gravity = data[0] elif name == "music": self.music = data[0] elif name == "init-script": self.init_script = data[0] elif name == "tilemap": tilemap = SuperTuxTileMap.from_sexpr(data) self.tilemaps.append(tilemap) # self.editormap.add_layer(tilemap.tilemap_layer) # GRUMBEL: incorrect if tilemap.solid: self.width = max(self.width, tilemap.tilemap_layer.width) self.height = max(self.height, tilemap.tilemap_layer.height) self.editormap.set_bounding_rect(Rect(0, 0, self.width * 32, self.height * 32)) self.object_layer.add_object(ObjMapTilemapObject(tilemap.tilemap_layer, tilemap)) else: obj = supertux_gameobj_factory.create_gameobj(name, data) if obj is None: logging.error("Couldn't resolve object type: " + name) logging.warning("Sector: Unhandled tag: " + name) else: if name == "camera": self.camera = obj self.objects.append(obj) self.object_layer.add_object(obj.objmap_object) self.editormap.metadata = self
def auto_crop(self): rect = Rect(0, 0, 0, 0) for y, x in itertools.product(range(0, self.field.height), range(0, self.field.width)): if self.field.at(x, y) != 0: rect.top = y break for y, x in itertools.product(reversed(range(0, self.field.height)), range(0, self.field.width)): if self.field.at(x, y) != 0: rect.bottom = y + 1 break for x, y in itertools.product(range(0, self.field.width), range(0, self.field.height)): if self.field.at(x, y) != 0: rect.left = x break for x, y in itertools.product(reversed(range(0, self.field.width)), range(0, self.field.height)): if self.field.at(x, y) != 0: rect.right = x + 1 break if rect.width != 0: self.resize(rect.width, rect.height, -rect.left, -rect.top) else: self.field = Field.from_size(1, 1) self.field.put(0, 0, 0) self.set_opaque()
def execute(self): assert self.points != [] # Calc bounding rect rect = Rect(self.points[0].x, self.points[0].y, self.points[0].x + self.brush.width, self.points[0].y + self.brush.height) for point in self.points: rect.left = min(rect.left, point.x) rect.top = min(rect.top, point.y) rect.right = max(rect.right, point.x + self.brush.width) rect.bottom = max(rect.bottom, point.y + self.brush.height) self.pos.x = rect.left self.pos.y = rect.top self.redo_brush = TileBrush.from_field(self.tilemap.field.copy(), rect.width, rect.height, -self.pos.x, -self.pos.y) # FIXME: undo_field is unneeded, should just record the overwritten color self.undo_brush = TileBrush.from_field(self.undo_field, rect.width, rect.height, -self.pos.x, -self.pos.y) self.redo_brush.set_opaque() self.undo_brush.set_opaque() self.undo_field = None
def draw(self, gc): tilemap = ToolContext.current.tilemap_layer if not tilemap: return tile_size = tilemap.get_tileset().get_tile_size() # Draw the brush: for y in range(0, ToolContext.current.tile_brush.height): for x in range(0, ToolContext.current.tile_brush.width): tile = tilemap.get_tileset().create( ToolContext.current.tile_brush.at(x, y)) if tile: sprite = tile.get_sprite() sprite.set_alpha(0.5) sprite.draw((self.current_tile.x + x) * tile_size, (self.current_tile.y + y) * tile_size, gc) gc.fill_rect( Rect( Point((self.current_tile.x + x) * tile_size, (self.current_tile.y + y) * tile_size), Size(tile_size, tile_size)), Color(255, 255, 255, 100)) elif ToolContext.current.tile_brush.is_opaque(): gc.fill_rect( Rect( Point((self.current_tile.x + x) * tile_size, (self.current_tile.y + y) * tile_size), Size(tile_size, tile_size)), Color(255, 255, 255, 100)) else: gc.fill_rect( Rect( Point((self.current_tile.x + x) * tile_size, (self.current_tile.y + y) * tile_size), Size(tile_size, tile_size)), Color(255, 255, 255, 50))
def draw(self, gc): gc.fill_rect(Rect(Point(self.pos) - Point(16, 16), Size(32, 32)), Color(200, 255, 200)) if self.next_node: gc.draw_line(int(self.pos.x), int(self.pos.y), int((self.pos.x + self.next_node.pos.x) / 2), int((self.pos.y + self.next_node.pos.y) / 2), Color(255, 255, 0)) gc.draw_line(int((self.pos.x + self.next_node.pos.x) / 2), int((self.pos.y + self.next_node.pos.y) / 2), int(self.next_node.pos.x), int(self.next_node.pos.y), Color(255, 0, 0))
def __init__(self): self.background_color = Color(100, 80, 100) self.foreground_color = Color(255, 80, 255) self.modified = False self.serial = 0 self._has_bounding_rect = False self.bounding_rect = Rect(0, 0, 0, 0) self.layers = [] self.redo_stack = [] self.undo_stack = [] # Index in undo_stack + redo_stack, all with index <= are saved. self.save_pointer = 0 self.sig_change = Signal() self.metadata = None self.draw_grid = False
def draw_foreground(self, gc): bounding_rect = self.get_bounding_rect() if bounding_rect != Rect(0, 0, 0, 0): if self.draw_grid: rect = Rect(gc.get_clip_rect()) start_x = rect.left // 32 start_y = rect.top // 32 end_x = rect.right // 32 + 1 end_y = rect.bottom // 32 + 1 tile_size = 32 for y in range(start_y, end_y): gc.draw_line(start_x * tile_size, y * tile_size, end_x * tile_size, y * tile_size, Color(150, 150, 150)) for x in range(start_x, end_x): gc.draw_line(x * tile_size, start_y * tile_size, x * tile_size, end_y * tile_size, Color(150, 150, 150)) # bounding rect gc.draw_rect(bounding_rect, self.foreground_color)
def get_selection(self): selection = Rect(self.current_pos.x, self.current_pos.y, self.region_select_start.x, self.region_select_start.y) selection.normalize() selection.right += 1 selection.bottom += 1 selection.left = min(max(0, selection.left), self.columns) selection.right = min(max(0, selection.right), self.columns) selection.top = max(0, selection.top) return selection
def paintEvent(self, event): painter = QPainter(self) gc = GraphicContext(painter) brush = ToolContext.current.tile_brush start_row = event.rect().top() // self.cell_size end_row = (event.rect().bottom() + self.cell_size - 1) // self.cell_size end_index = min(end_row * self.columns, len(self.tiles)) # Draw tiles for i in range(start_row * self.columns, end_index): x = i % self.columns y = i // self.columns tile = self.tileset.create(self.tiles[i]) rect = Rect(Point(int(x * self.cell_size), int(y * self.cell_size)), Size(self.cell_size, self.cell_size)) if tile: sprite = tile.get_sprite() sprite.set_scale(self.scale, self.scale) sprite.draw(int(x * self.cell_size), int(y * self.cell_size), gc) # Use grid in the tileselector gc.draw_rect(rect, Color(0, 0, 0, 128)) # mark the currently selected tile if brush.width == 1 and brush.height == 1 and brush.at(0, 0) == self.tiles[i]: gc.fill_rect(rect, Color(0, 0, 255, 100)) elif self.mouse_over_tile == i and self.has_focus: gc.fill_rect(rect, Color(0, 0, 255, 20)) # draw rectangle selection if self.region_select: rect = self.get_selection() rect.top *= self.cell_size rect.bottom *= self.cell_size rect.left *= self.cell_size rect.right *= self.cell_size gc.fill_rect(rect, Color(0, 0, 255, 100))
def get_bounding_rect(self): if self._has_bounding_rect: return self.bounding_rect else: init = False rect = Rect(0, 0, 0, 0) for layer in self.layers: if layer.has_bounding_rect(): if not init: rect = layer.get_bounding_rect() init = True else: other = layer.get_bounding_rect() rect.top = min(rect.top, other.top) rect.bottom = max(rect.bottom, other.bottom) rect.left = min(rect.left, other.left) rect.right = max(rect.right, other.right) return rect
def draw_background(self, gc): bounding_rect = self.get_bounding_rect() if bounding_rect != Rect(0, 0, 0, 0): gc.fill_rect(bounding_rect, self.background_color)
class TileSelection: def __init__(self): self.tilemap = None self.start_pos = None self.selection = None self.active = False def start(self, tilemap, pos): self.tilemap = tilemap self.active = True self.start_pos = pos self.update(self.start_pos) def update(self, pos): self.selection = Rect(min(self.start_pos.x, pos.x), min(self.start_pos.y, pos.y), max(self.start_pos.x, pos.x) + 1, max(self.start_pos.y, pos.y) + 1) def is_active(self): return self.active def clear(self): self.selection = Rect() self.active = False def draw(self, gc, color=Color(255, 255, 255, 100)): tile_size = self.tilemap.get_tileset().get_tile_size() gc.fill_rect( Rect(self.selection.left * tile_size, self.selection.top * tile_size, self.selection.right * tile_size, self.selection.bottom * tile_size), color) def get_brush(self, field): sel = self.selection.copy() sel.normalize() if sel.left > field.width - 1 or \ sel.top > field.height - 1 or \ sel.right <= 0 or \ sel.bottom <= 0: # Selection is empty logging.error("Error: Invalid selection") brush = TileBrush(1, 1) brush.put(0, 0, 0) brush.set_opaque() return brush else: # Selection is valid # Cut the selection to the field size sel.left = max(0, sel.left) sel.top = max(0, sel.top) sel.right = min(sel.right, field.width) sel.bottom = min(sel.bottom, field.height) brush = TileBrush(sel.width, sel.height) for y in range(sel.top, sel.bottom): for x in range(sel.left, sel.right): brush.put(x - sel.left, y - sel.top, field.at(x, y)) return brush def get_rect(self): sel = self.selection.copy() sel.normalize() return sel
def update(self, pos): self.selection = Rect(min(self.start_pos.x, pos.x), min(self.start_pos.y, pos.y), max(self.start_pos.x, pos.x) + 1, max(self.start_pos.y, pos.y) + 1)
def draw(self, stroke, gc): if DrawerProperties.current.get_brush().is_null( ) or stroke.get_dab_count() == 0: return dabs = stroke.get_interpolated_dabs( DrawerProperties.current.get_spacing() * DrawerProperties.current.get_size(), DrawerProperties.current.get_spacing() * DrawerProperties.current.get_size()) for i, dab in enumerate(self.dabs): sprite = DrawerProperties.current.get_brush().get_sprite() color = DrawerProperties.current.get_color() sprite.set_color(color) sprite.set_alpha((color.get_alpha() / 255.0) * dab.pressure) sprite.set_scale( DrawerProperties.current.get_size() * dab.pressure, DrawerProperties.current.get_size() * dab.pressure) if gc is not None: # DO Multipass: # 1: GL_ZERO, GL_DST_ALPHA # 2: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA # brush.set_blend_func_separate(BlendFunc.zero, BlendFunc.dst_alpha, # BlendFunc.zero, BlendFunc.one) # brush.draw(dab.pos.x, dab.pos.y, gc) if self.mode == SpriteStrokeDrawer.DM_NORMAL: sprite.set_blend_func_separate( BlendFunc.src_alpha, BlendFunc.one_minus_src_alpha, BlendFunc.one, BlendFunc.one_minus_src_alpha) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) elif self.mode == SpriteStrokeDrawer.DM_ADDITION: sprite.set_blend_func_separate(BlendFunc.src_alpha, BlendFunc.one, BlendFunc.zero, BlendFunc.one) # BlendFunc.one, BlendFunc.one_minus_src_alpha) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) elif self.mode == SpriteStrokeDrawer.DM_ERASE: sprite.set_blend_func(BlendFunc.zero, BlendFunc.one_minus_src_alpha) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) elif self.mode == SpriteStrokeDrawer.DM_SMUDGE: if dab != dabs[0]: canvas = BitmapLayer.current.get_canvas() buffer = canvas.get_pixeldata( Rect( Point( int(self.dabs[i - 1].pos.x) - sprite.width / 2, int(self.dabs[i - 1].pos.y) - sprite.height / 2), Size(sprite.width, sprite.height))) surface = Surface(buffer) # surface.set_blend_func_separate(BlendFunc.src_alpha, BlendFunc.one_minus_src_alpha, # BlendFunc.one, BlendFunc.zero) surface.set_alignment(Origin.center) surface.set_alpha(0.5) # surface.set_scale(DrawerProperties.current.get_size(), # DrawerProperties.current.get_size()) surface.draw(dab.pos.x, dab.pos.y, gc.gc) else: print("Error: SpriteStrokeDrawer: Unknown draw mode: ", self.mode) else: if self.mode == SpriteStrokeDrawer.DM_NORMAL: sprite.set_blend_func(BlendFunc.src_alpha, BlendFunc.one_minus_src_alpha) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) elif self.mode == SpriteStrokeDrawer.DM_ADDITION: sprite.set_blend_func(BlendFunc.src_alpha, BlendFunc.one) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) elif self.mode == SpriteStrokeDrawer.DM_ERASE: sprite.set_blend_func(BlendFunc.zero, BlendFunc.one_minus_src_alpha) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) elif self.mode == SpriteStrokeDrawer.DM_SMUDGE: sprite.set_blend_func(BlendFunc.src_alpha, BlendFunc.one_minus_src_alpha) sprite.draw(dab.pos.x, dab.pos.y, gc.gc) else: print("Error: SpriteStrokeDrawer: Unknown draw mode:", self.mode)
def get_bounding_rect(self): return Rect(Point(0, 0), Size(self.field.width * self.tileset.get_tile_size(), self.field.height * self.tileset.get_tile_size()))
def draw(self, gc, pos=Point()): if self.hidden: return tile_size = self.tileset.get_tile_size() if False and self.background_color.get_alpha() != 0: gc.fill_rect(Rect(pos, Size(self.field.width * tile_size, self.field.height * tile_size)), self.background_color) # The visible rectangle rect = Rect(gc.get_clip_rect()) # max() here stops tiles off screen (below 0) from being drawn start_x = max(0, pos.x // tile_size) start_y = max(0, pos.y // tile_size) # min() here stops tiles off screen (above size of clip rect) from being drawn end_x = min(self.field.width + pos.x // tile_size, rect.right // tile_size + 1) end_y = min(self.field.height + pos.y // tile_size, rect.bottom // tile_size + 1) if self.foreground_color != Color(255, 255, 255, 255): for y in range(start_y, end_y): for x in range(start_x, end_x): # The coordinates on the field are from 0 - field.width tile_id = self.field.at(x - start_x, y - start_y) if tile_id: tile = self.tileset.create(tile_id) if tile: # skip transparent tile for faster draw sprite = tile.get_sprite() sprite.set_color(self.foreground_color) sprite.draw(x * tile_size, y * tile_size, gc) if self.draw_attribute: gc.fill_rect(Rect(Point(x, y), Size(self.tileset.get_tile_size(), self.tileset.get_tile_size())), tile.get_attribute_color()) else: for y in range(start_y, end_y): for x in range(start_x, end_x): tile_id = self.field.at(x - start_x, y - start_y) if tile_id: # skip transparent tile for faster draw tile = self.tileset.create(self.field.at(x - start_x, y - start_y)) if tile: tile.get_sprite().draw(x * tile_size, y * tile_size, gc) if self.draw_attribute: gc.fill_rect(Rect(Point(x, y), Size(self.tileset.get_tile_size(), self.tileset.get_tile_size())), tile.get_attribute_color()) if self.draw_grid: for y in range(start_y, end_y): gc.draw_line(start_x * tile_size, y * tile_size, end_x * tile_size, y * tile_size, Color(150, 150, 150)) for x in range(start_x, end_x): gc.draw_line(x * tile_size, start_y * tile_size, x * tile_size, end_y * tile_size, Color(150, 150, 150))
def draw(self, gc): gc.fill_rect(Rect(self.get_bound_rect()), self.color)
def clear(self): self.selection = Rect() self.active = False
def on_a_key(x, y): pos = self.editor_map.screen2world(Point(x, y)) rectobj = ObjMapRectObject(Rect(pos, Size(128, 64)), Color(0, 255, 255, 155), None) self.workspace.get_map().metadata.objects.add_object(rectobj)
def main(): flexlay = Flexlay("Simple Editor") gui_manager = flexlay.create_gui_manager() config = Config.create("simple-editor") button_panel = gui_manager.create_button_panel(horizontal=True) def on_object_tool(): workspace.set_tool(1, objtool) workspace.set_tool(2, workspace_move_tool) workspace.set_tool(3, TilePaintTool()) button_panel.add_text("ObjectTool", on_object_tool) def on_tile_tool(): workspace.set_tool(1, tilemap_paint_tool) workspace.set_tool(2, workspace_move_tool) workspace.set_tool(3, tilemap_paint_tool) button_panel.add_text("TileTool", on_tile_tool) def on_generic_dialog(): dialog = gui_manager.create_generic_dialog("Generic Dialog") dialog.add_bool("An Bool:", True) dialog.add_int("An Int:", 5) dialog.add_float("An Int:", 5.0) dialog.add_string("An String:", "String") dialog.add_enum("An Enum:", ["String", "Foo", "bar"], 0) dialog.set_ok_callback(lambda: print(dialog.get_values())) button_panel.add_text("Generic Dialog", on_generic_dialog) menubar = gui_manager.create_menubar() file_menu = menubar.add_menu("&File") file_menu.add_item("Open...", lambda: print("Open")) file_menu.add_item("Save...", lambda: print("Save")) file_menu.add_item("Quit...", lambda: print("Quit")) view_menu = menubar.add_menu("&View") view_menu.add_item("Zoom In", lambda: print("Zoom In")) view_menu.add_item("Zoom Out", lambda: print("Zoom Out")) view_menu.add_item("Reset Zoom", lambda: print("Reset Zoom")) editor_map_component = gui_manager.create_editor_map_component() editormap = EditorMap() tileset = Tileset(32) tileset.add_tile(0, Tile(PixelBuffer.from_file("data/images/icons16/resize1.png"), Sprite.from_file("data/images/icons16/resize1.png"))) tileset.add_tile(1, Tile(PixelBuffer.from_file("data/images/icons16/resize_vert.png"), Sprite.from_file("data/images/icons16/resize_vert.png"))) tilemap = TilemapLayer(tileset, 20, 10) TilemapLayer.current = tilemap tilemap.set_draw_grid(True) object_layer = ObjectLayer() editormap.add_layer(tilemap) editormap.add_layer(object_layer) for i in range(20): obj = ObjMapRectObject(Rect(Point(random.randint(0, 499), random.randint(0, 499)), Size(32, 32)), Color(0, 0, 255), None) object_layer.add_object(obj) workspace = editor_map_component.get_workspace() workspace.set_map(editormap) ToolContext() ToolContext.current.tile_brush.put(0, 0, 1) workspace_move_tool = WorkspaceMoveTool() objtool = ObjMapSelectTool(gui_manager) tilemap_paint_tool = TilePaintTool() # tilemap_paint_tool.set_brush(ToolContext.current.tile_brush) workspace.set_tool(1, objtool) workspace.set_tool(2, workspace_move_tool) # workspace.set_tool(1, tilemap_paint_tool) # workspace.set_tool(3, tilemap_paint_tool) object_selector = gui_manager.create_object_selector(40, 40) object_selector.add_brush(ObjectBrush(Sprite.from_file("data/images/icons16/resize1.png"), None)) object_selector.add_brush(ObjectBrush(Sprite.from_file("data/images/icons16/resize2.png"), None)) tile_selector = gui_manager.create_tile_selector() # tile_selector.set_tiles("All the tiles", tileset.get_tiles()) # tile_selector.set_tiles("All the tiles again", tileset.get_tiles()) # tile_selector.set_tiles("And again", tileset.get_tiles()) print("Successs!") gui_manager.run()
def get_bounding_rect(self): # FIXME: Do we need to handle its position here or does the Layer keep care of that? return Rect(Point(0, 0), Size(self.surface.width, self.surface.height))
def paintEvent(self, event): if not self.parent.get_workspace().get_map(): return if not self.parent or not self.parent.get_workspace(): return painter = QPainter(self) gc = GraphicContext(painter) gc.push_modelview() # FIXME: Do this only on map changes if self.last_serial != self.parent.get_workspace().get_map( ).get_serial(): # or editor_map != parent.get_workspace().get_map()) self.update_minimap() self.last_serial = self.parent.get_workspace().get_map( ).get_serial() self.editor_map = self.parent.get_workspace().get_map() if True: # Draw background color gc.fill_rect(Rect(Point(0, 0), Size(self.width(), self.height())), Color(200, 200, 200, 225)) # FIXME: This doesn't work all that well tilemap = ToolContext.current.tilemap_layer if tilemap and tilemap.height != 0 and tilemap.width != 0: tile_size = tilemap.get_tileset().get_tile_size() map_width = tilemap.width * tile_size map_height = tilemap.height * tile_size small_tile_size = Size(tile_size * self.width() / map_width + 1, tile_size * self.height() / map_height + 1) field = tilemap.field # FIXME: No current tileset if False: for y in range(0, field.height): for x in range(0, field.width): tile = tilemap.get_tileset().create(field.at(x, y)) if tile: gc.fill_rect( Rect( Point((x * tile_size) * self.width() / map_width, (y * tile_size) * self.height() / map_height), small_tile_size), tile.get_color()) if self.minimap_surface: self.minimap_surface.draw( Rect(Point(0, 0), Size(self.width(), self.height()))) # Draw cursor rect = self.parent.get_clip_rect() screen_rect = Rect( Point(rect.left * self.width() / map_width, rect.top * self.height() / map_height), Size(rect.width * self.width() / map_width, rect.height * self.height() / map_height)) gc.fill_rect(screen_rect, Color(255, 255, 0, 50)) gc.draw_rect(screen_rect, Color(0, 0, 0)) gc.pop_modelview()