added drag-selection
This commit is contained in:
		@@ -39,17 +39,17 @@ class Editor:
 | 
			
		||||
            self.ZOOMS
 | 
			
		||||
        ))
 | 
			
		||||
        self.is_creating_node: bool = False
 | 
			
		||||
        self.typing: bool = False
 | 
			
		||||
        self.state: State = State.STOPPING
 | 
			
		||||
        self.graph = Graph()
 | 
			
		||||
        self.typing_text: str = ""
 | 
			
		||||
        self.node_candidate_pos: tuple[int, int] = None
 | 
			
		||||
        self.node_radius: int = 10
 | 
			
		||||
        self.line_size: int = (int) (self.node_radius / 5)
 | 
			
		||||
        self.line_size: int = int(self.node_radius / 5)
 | 
			
		||||
        self.edge_detect_radius: int = 3 * self.line_size
 | 
			
		||||
        self.selected_nodes: list[int] = []
 | 
			
		||||
        self.selected_edges: list[int] = []
 | 
			
		||||
        self.previously_created_nodes: list[int] = []
 | 
			
		||||
        self.selection_rectangle: list[tuple[int, int], tuple[int, int]] = None
 | 
			
		||||
 | 
			
		||||
    def mainloop(self) -> None:
 | 
			
		||||
        self.state = State.LOADING
 | 
			
		||||
@@ -61,6 +61,8 @@ class Editor:
 | 
			
		||||
                if not self.image_handler.loading:
 | 
			
		||||
                    self.state = State.RUNNING
 | 
			
		||||
            elif self.state == State.RUNNING:
 | 
			
		||||
                if self.selection_rectangle != None:
 | 
			
		||||
                    self.expand_selection_rect()
 | 
			
		||||
                self.render()
 | 
			
		||||
            self.clock.tick(30)
 | 
			
		||||
 | 
			
		||||
@@ -75,9 +77,8 @@ class Editor:
 | 
			
		||||
                self.width = event.x
 | 
			
		||||
                self.height = event.y
 | 
			
		||||
            elif event.type == pygame.KEYDOWN:
 | 
			
		||||
                if self.typing:
 | 
			
		||||
                if self.is_creating_node:
 | 
			
		||||
                    if event.key == pygame.K_ESCAPE:
 | 
			
		||||
                        self.typing = False
 | 
			
		||||
                        self.is_creating_node = False
 | 
			
		||||
                        self.node_candidate_pos = None
 | 
			
		||||
                        self.typing_text = ""
 | 
			
		||||
@@ -106,12 +107,13 @@ class Editor:
 | 
			
		||||
                elif event.button == 1:
 | 
			
		||||
                    if keys[pygame.K_LCTRL]:
 | 
			
		||||
                        self.left_drag_pos = event.pos
 | 
			
		||||
                    elif keys[pygame.K_LALT]:
 | 
			
		||||
                        self.create_selection_rect(keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT])
 | 
			
		||||
                    else:
 | 
			
		||||
                        self.select_object(keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT])
 | 
			
		||||
                elif event.button == 3:
 | 
			
		||||
                    self.node_candidate_pos = self.screen_to_world(event.pos[0], event.pos[1])
 | 
			
		||||
                    self.is_creating_node = True
 | 
			
		||||
                    self.typing = True
 | 
			
		||||
                elif event.button == 4:
 | 
			
		||||
                    self.zoom_in()
 | 
			
		||||
                elif event.button == 5:
 | 
			
		||||
@@ -120,7 +122,10 @@ class Editor:
 | 
			
		||||
                if event.button == 2:
 | 
			
		||||
                    self.mid_drag_pos = None
 | 
			
		||||
                elif event.button == 1:
 | 
			
		||||
                    self.left_drag_pos = None
 | 
			
		||||
                    if keys[pygame.K_LCTRL]:
 | 
			
		||||
                        self.left_drag_pos = None
 | 
			
		||||
                    elif self.selection_rectangle != None:
 | 
			
		||||
                        self.release_selection_rect(keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT])
 | 
			
		||||
 | 
			
		||||
        if keys[pygame.K_LEFT]:
 | 
			
		||||
            self.center[0] -= 4 / self.zoom
 | 
			
		||||
@@ -183,6 +188,8 @@ class Editor:
 | 
			
		||||
 | 
			
		||||
        self.render_graph()
 | 
			
		||||
 | 
			
		||||
        self.render_selection_rect()
 | 
			
		||||
 | 
			
		||||
        pygame.draw.line(self.win, (150, 150, 150), [w2 - self.CROSSHAIR_SIZE, h2], [w2 + self.CROSSHAIR_SIZE, h2])
 | 
			
		||||
        pygame.draw.line(self.win, (150, 150, 150), [w2, h2 - self.CROSSHAIR_SIZE], [w2, h2 + self.CROSSHAIR_SIZE])
 | 
			
		||||
        self.render_zoom_slider()
 | 
			
		||||
@@ -262,9 +269,11 @@ class Editor:
 | 
			
		||||
        hover_index, is_node = self.get_hover_object()
 | 
			
		||||
        if is_node:
 | 
			
		||||
            self.render_nodes()
 | 
			
		||||
            self.render_hover_node(hover_index)
 | 
			
		||||
            if self.selection_rectangle == None:
 | 
			
		||||
                self.render_hover_node(hover_index)
 | 
			
		||||
        else:
 | 
			
		||||
            self.render_hover_edge(hover_index)
 | 
			
		||||
            if self.selection_rectangle == None:
 | 
			
		||||
                self.render_hover_edge(hover_index)
 | 
			
		||||
            self.render_nodes()
 | 
			
		||||
 | 
			
		||||
    def render_edges(self) -> None:
 | 
			
		||||
@@ -296,6 +305,16 @@ class Editor:
 | 
			
		||||
            pygame.draw.line(self.win, (0, 0, 0), self.world_to_screen(node_1.x, node_1.z), self.world_to_screen(node_2.x, node_2.z), self.edge_detect_radius)
 | 
			
		||||
            color = (0, 255, 255) if edge_index in self.selected_edges else (255, 0, 0)
 | 
			
		||||
            pygame.draw.line(self.win, color, self.world_to_screen(node_1.x, node_1.z), self.world_to_screen(node_2.x, node_2.z), self.line_size)
 | 
			
		||||
    
 | 
			
		||||
    def render_selection_rect(self):
 | 
			
		||||
        rect = self.selection_rectangle
 | 
			
		||||
        if rect != None:
 | 
			
		||||
            left = min(rect[0][0], rect[1][0])
 | 
			
		||||
            top = min(rect[0][1], rect[1][1])
 | 
			
		||||
            width = abs(rect[0][0] - rect[1][0])
 | 
			
		||||
            height = abs(rect[0][1] - rect[1][1])
 | 
			
		||||
            pygame.draw.rect(self.win, (32, 32, 32), pygame.Rect(left, top, width, height), self.line_size)
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
    def set_zoom(self, zoom_i: int) -> None:
 | 
			
		||||
        self.zoom_i = max(0, min(len(self.ZOOMS) - 1, zoom_i))
 | 
			
		||||
@@ -383,7 +402,6 @@ class Editor:
 | 
			
		||||
        self.graph.add_node(self.node_candidate_pos[0], self.node_candidate_pos[1], self.typing_text)
 | 
			
		||||
        self.typing_text = ""
 | 
			
		||||
        self.node_candidate_pos = None
 | 
			
		||||
        self.typing = False
 | 
			
		||||
        self.is_creating_node = False
 | 
			
		||||
        if len(self.selected_nodes) == 1:
 | 
			
		||||
            self.previously_created_nodes.append(self.selected_nodes[0])
 | 
			
		||||
@@ -479,6 +497,41 @@ class Editor:
 | 
			
		||||
        if n != 0:
 | 
			
		||||
            self.selected_nodes.append(self.previously_created_nodes[n - 1])
 | 
			
		||||
            self.previously_created_nodes.pop()
 | 
			
		||||
    
 | 
			
		||||
    def create_selection_rect(self, shifting = False):
 | 
			
		||||
        if not shifting:
 | 
			
		||||
            self.clear_selection()
 | 
			
		||||
            self.previously_created_nodes = []
 | 
			
		||||
        mouse_pos = pygame.mouse.get_pos()
 | 
			
		||||
        self.selection_rectangle = [mouse_pos, mouse_pos]
 | 
			
		||||
    
 | 
			
		||||
    def expand_selection_rect(self):
 | 
			
		||||
        self.selection_rectangle[1] = pygame.mouse.get_pos()
 | 
			
		||||
    
 | 
			
		||||
    def release_selection_rect(self, shifting = False):
 | 
			
		||||
        if not shifting:
 | 
			
		||||
            self.clear_selection()
 | 
			
		||||
        self.previously_created_nodes = []
 | 
			
		||||
        rect = self.selection_rectangle
 | 
			
		||||
        left = min(rect[0][0], rect[1][0])
 | 
			
		||||
        top = min(rect[0][1], rect[1][1])
 | 
			
		||||
        right = max(rect[0][0], rect[1][0])
 | 
			
		||||
        bottom = max(rect[0][1], rect[1][1])
 | 
			
		||||
        for node in self.graph.nodes:
 | 
			
		||||
            pos = self.world_to_screen(node.x, node.z)
 | 
			
		||||
            if left <= pos[0] <= right and top <= pos[1] <= bottom:
 | 
			
		||||
                if node.index not in self.selected_nodes:
 | 
			
		||||
                    self.selected_nodes.append(node.index)
 | 
			
		||||
            print(left, "<=", pos[0], "<=", right)
 | 
			
		||||
            print(top, "<=", pos[1], "<=", bottom)
 | 
			
		||||
        for edge in self.graph.edges:
 | 
			
		||||
            pos = self.world_to_screen(*self.graph.get_edge_center(edge.index))
 | 
			
		||||
            if left <= pos[0] <= right and top <= pos[1] <= bottom:
 | 
			
		||||
                if edge.index not in self.selected_edges:
 | 
			
		||||
                    self.selected_edges.append(edge.index)
 | 
			
		||||
            print(left, "<=", pos[0], "<=", right)
 | 
			
		||||
            print(top, "<=", pos[1], "<=", bottom)
 | 
			
		||||
        self.selection_rectangle = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -489,5 +542,4 @@ class Editor:
 | 
			
		||||
class State(Enum):
 | 
			
		||||
    STOPPING = auto()
 | 
			
		||||
    LOADING = auto()
 | 
			
		||||
    RUNNING = auto()
 | 
			
		||||
    CREATING_NODE = auto()
 | 
			
		||||
    RUNNING = auto()
 | 
			
		||||
@@ -9,8 +9,8 @@ class Graph:
 | 
			
		||||
        self.edges: list[Edge] = []
 | 
			
		||||
        self.nodes: list[Node] = []
 | 
			
		||||
 | 
			
		||||
    def add_node(self, x: int, y: int, name: str) -> None:
 | 
			
		||||
        self.nodes.append(Node(x, y, name, len(self.nodes)))
 | 
			
		||||
    def add_node(self, x: int, z: int, name: str) -> None:
 | 
			
		||||
        self.nodes.append(Node(x, z, name, len(self.nodes)))
 | 
			
		||||
 | 
			
		||||
    def add_edge(self, start_index: int, end_index: int, length: float) -> None:
 | 
			
		||||
        self.edges.append(Edge(start_index, end_index, length, len(self.edges)))
 | 
			
		||||
@@ -47,6 +47,12 @@ class Graph:
 | 
			
		||||
    
 | 
			
		||||
    def get_edge_nodes(self, edge: Edge) -> tuple[Node, Node]:
 | 
			
		||||
        return self.nodes[edge.start], self.nodes[edge.end]
 | 
			
		||||
    
 | 
			
		||||
    def get_edge_center(self, edge_index: int) -> tuple[float, float]:
 | 
			
		||||
        edge = self.edges[edge_index]
 | 
			
		||||
        start_n = self.nodes[edge.start]
 | 
			
		||||
        end_n = self.nodes[edge.end]
 | 
			
		||||
        return (start_n.x + end_n.x) / 2, (start_n.z + end_n.z) / 2
 | 
			
		||||
 | 
			
		||||
    def edges_adjacent_to(self, node_i: int) -> Iterator[Edge]:
 | 
			
		||||
        return filter(lambda e: e.start == node_i or e.end == node_i, self.edges)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user