added drag-selection
This commit is contained in:
parent
77f11a7440
commit
efe158f83f
@ -39,17 +39,17 @@ class Editor:
|
|||||||
self.ZOOMS
|
self.ZOOMS
|
||||||
))
|
))
|
||||||
self.is_creating_node: bool = False
|
self.is_creating_node: bool = False
|
||||||
self.typing: bool = False
|
|
||||||
self.state: State = State.STOPPING
|
self.state: State = State.STOPPING
|
||||||
self.graph = Graph()
|
self.graph = Graph()
|
||||||
self.typing_text: str = ""
|
self.typing_text: str = ""
|
||||||
self.node_candidate_pos: tuple[int, int] = None
|
self.node_candidate_pos: tuple[int, int] = None
|
||||||
self.node_radius: int = 10
|
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.edge_detect_radius: int = 3 * self.line_size
|
||||||
self.selected_nodes: list[int] = []
|
self.selected_nodes: list[int] = []
|
||||||
self.selected_edges: list[int] = []
|
self.selected_edges: list[int] = []
|
||||||
self.previously_created_nodes: list[int] = []
|
self.previously_created_nodes: list[int] = []
|
||||||
|
self.selection_rectangle: list[tuple[int, int], tuple[int, int]] = None
|
||||||
|
|
||||||
def mainloop(self) -> None:
|
def mainloop(self) -> None:
|
||||||
self.state = State.LOADING
|
self.state = State.LOADING
|
||||||
@ -61,6 +61,8 @@ class Editor:
|
|||||||
if not self.image_handler.loading:
|
if not self.image_handler.loading:
|
||||||
self.state = State.RUNNING
|
self.state = State.RUNNING
|
||||||
elif self.state == State.RUNNING:
|
elif self.state == State.RUNNING:
|
||||||
|
if self.selection_rectangle != None:
|
||||||
|
self.expand_selection_rect()
|
||||||
self.render()
|
self.render()
|
||||||
self.clock.tick(30)
|
self.clock.tick(30)
|
||||||
|
|
||||||
@ -75,9 +77,8 @@ class Editor:
|
|||||||
self.width = event.x
|
self.width = event.x
|
||||||
self.height = event.y
|
self.height = event.y
|
||||||
elif event.type == pygame.KEYDOWN:
|
elif event.type == pygame.KEYDOWN:
|
||||||
if self.typing:
|
if self.is_creating_node:
|
||||||
if event.key == pygame.K_ESCAPE:
|
if event.key == pygame.K_ESCAPE:
|
||||||
self.typing = False
|
|
||||||
self.is_creating_node = False
|
self.is_creating_node = False
|
||||||
self.node_candidate_pos = None
|
self.node_candidate_pos = None
|
||||||
self.typing_text = ""
|
self.typing_text = ""
|
||||||
@ -106,12 +107,13 @@ class Editor:
|
|||||||
elif event.button == 1:
|
elif event.button == 1:
|
||||||
if keys[pygame.K_LCTRL]:
|
if keys[pygame.K_LCTRL]:
|
||||||
self.left_drag_pos = event.pos
|
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:
|
else:
|
||||||
self.select_object(keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT])
|
self.select_object(keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT])
|
||||||
elif event.button == 3:
|
elif event.button == 3:
|
||||||
self.node_candidate_pos = self.screen_to_world(event.pos[0], event.pos[1])
|
self.node_candidate_pos = self.screen_to_world(event.pos[0], event.pos[1])
|
||||||
self.is_creating_node = True
|
self.is_creating_node = True
|
||||||
self.typing = True
|
|
||||||
elif event.button == 4:
|
elif event.button == 4:
|
||||||
self.zoom_in()
|
self.zoom_in()
|
||||||
elif event.button == 5:
|
elif event.button == 5:
|
||||||
@ -120,7 +122,10 @@ class Editor:
|
|||||||
if event.button == 2:
|
if event.button == 2:
|
||||||
self.mid_drag_pos = None
|
self.mid_drag_pos = None
|
||||||
elif event.button == 1:
|
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]:
|
if keys[pygame.K_LEFT]:
|
||||||
self.center[0] -= 4 / self.zoom
|
self.center[0] -= 4 / self.zoom
|
||||||
@ -183,6 +188,8 @@ class Editor:
|
|||||||
|
|
||||||
self.render_graph()
|
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 - 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])
|
pygame.draw.line(self.win, (150, 150, 150), [w2, h2 - self.CROSSHAIR_SIZE], [w2, h2 + self.CROSSHAIR_SIZE])
|
||||||
self.render_zoom_slider()
|
self.render_zoom_slider()
|
||||||
@ -262,9 +269,11 @@ class Editor:
|
|||||||
hover_index, is_node = self.get_hover_object()
|
hover_index, is_node = self.get_hover_object()
|
||||||
if is_node:
|
if is_node:
|
||||||
self.render_nodes()
|
self.render_nodes()
|
||||||
self.render_hover_node(hover_index)
|
if self.selection_rectangle == None:
|
||||||
|
self.render_hover_node(hover_index)
|
||||||
else:
|
else:
|
||||||
self.render_hover_edge(hover_index)
|
if self.selection_rectangle == None:
|
||||||
|
self.render_hover_edge(hover_index)
|
||||||
self.render_nodes()
|
self.render_nodes()
|
||||||
|
|
||||||
def render_edges(self) -> None:
|
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)
|
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)
|
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)
|
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:
|
def set_zoom(self, zoom_i: int) -> None:
|
||||||
self.zoom_i = max(0, min(len(self.ZOOMS) - 1, zoom_i))
|
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.graph.add_node(self.node_candidate_pos[0], self.node_candidate_pos[1], self.typing_text)
|
||||||
self.typing_text = ""
|
self.typing_text = ""
|
||||||
self.node_candidate_pos = None
|
self.node_candidate_pos = None
|
||||||
self.typing = False
|
|
||||||
self.is_creating_node = False
|
self.is_creating_node = False
|
||||||
if len(self.selected_nodes) == 1:
|
if len(self.selected_nodes) == 1:
|
||||||
self.previously_created_nodes.append(self.selected_nodes[0])
|
self.previously_created_nodes.append(self.selected_nodes[0])
|
||||||
@ -479,6 +497,41 @@ class Editor:
|
|||||||
if n != 0:
|
if n != 0:
|
||||||
self.selected_nodes.append(self.previously_created_nodes[n - 1])
|
self.selected_nodes.append(self.previously_created_nodes[n - 1])
|
||||||
self.previously_created_nodes.pop()
|
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):
|
class State(Enum):
|
||||||
STOPPING = auto()
|
STOPPING = auto()
|
||||||
LOADING = auto()
|
LOADING = auto()
|
||||||
RUNNING = auto()
|
RUNNING = auto()
|
||||||
CREATING_NODE = auto()
|
|
@ -9,8 +9,8 @@ class Graph:
|
|||||||
self.edges: list[Edge] = []
|
self.edges: list[Edge] = []
|
||||||
self.nodes: list[Node] = []
|
self.nodes: list[Node] = []
|
||||||
|
|
||||||
def add_node(self, x: int, y: int, name: str) -> None:
|
def add_node(self, x: int, z: int, name: str) -> None:
|
||||||
self.nodes.append(Node(x, y, name, len(self.nodes)))
|
self.nodes.append(Node(x, z, name, len(self.nodes)))
|
||||||
|
|
||||||
def add_edge(self, start_index: int, end_index: int, length: float) -> None:
|
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)))
|
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]:
|
def get_edge_nodes(self, edge: Edge) -> tuple[Node, Node]:
|
||||||
return self.nodes[edge.start], self.nodes[edge.end]
|
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]:
|
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)
|
return filter(lambda e: e.start == node_i or e.end == node_i, self.edges)
|
||||||
|
Loading…
Reference in New Issue
Block a user