Select Git revision
map_edit.py
map_edit.py 5.72 KiB
import dearpygui.dearpygui as dpg
import numpy as np
from utils import get_map_window_value, get_config_file_path, is_drawing, get_current_action, set_map_window_value, get_emission_points, get_prev_coords, get_height_map_file_path
from map_edit_constants import EMISSION_POINT_COLOR
from dynamic_ui import add_emission_point_and_update_ui
def load_height_map(file_path):
with open(file_path, "r", encoding='utf-8') as file:
lines = file.readlines()[1:]
height_map = [list(map(int, line.strip().split())) for line in lines]
return np.array(height_map, dtype=np.float64)
def dump_height_map(height_map, file_path):
with open(file_path, "w", encoding="utf-8") as file:
w, h = height_map.shape
height_map *= get_map_window_value('max_height')
file.write(f"{w} {h}\n")
for row in height_map:
file.write(" ".join(list(map(str, map(int, row)))) + "\n")
def update_texture():
if get_config_file_path():
emission_points = get_emission_points()
for n in emission_points:
x = int(emission_points[n]['xpos'])
y = int(emission_points[n]['ypos'])
coords = get_triangle_coords(x, y)
tag = f'emission_point_{n}_triangle'
if not dpg.does_item_exist(tag):
dpg.draw_polygon(coords, color=EMISSION_POINT_COLOR, fill=(255, 0, 0, 255), tag=tag, parent='map_drawlist', thickness=0)
texture_map = np.repeat(get_map_window_value(f'{dpg.get_value('layer')}_map'), 4)
texture_map[3::4] = (texture_map[::4] != 0)
dpg.set_value(f'map_{dpg.get_value('layer')}_texture', texture_map)
def mouse_pos_to_height_map_coords(coords):
return map(int, coords)
def check_coords(x, y, w, h):
return 0 <= x <= x + w <= dpg.get_item_width('map_child_window') and 0 <= y <= y + h <= dpg.get_item_height('map_child_window')
def get_rect(cur_pos, end_pos):
x1, y1 = mouse_pos_to_height_map_coords(cur_pos)
x2, y2 = mouse_pos_to_height_map_coords(end_pos)
if y2 < y1:
y1, y2 = y2, y1
if x2 < x1:
x1, x2 = x2, x1
return y1, y2, x1, x2
def mouse_down_callback():
if not get_height_map_file_path():
return
if not dpg.is_item_focused('map_child_window'):
return
if not is_drawing():
set_map_window_value('prev_coords', dpg.get_drawing_mouse_pos())
set_map_window_value('drawing', True)
else:
if get_current_action() == 'erase' or get_current_action() == 'draw_rect':
x, y = dpg.get_drawing_mouse_pos()
px, py = get_prev_coords()
w, h = abs(x - px), abs(y - py)
x, y = min(x, px), min(y, py)
if w > 0 and h > 0 and check_coords(x, y, w, h):
dpg.set_item_pos('drawing_frame', [min(x, px), min(y, py)])
dpg.set_item_width('drawing_frame', w)
dpg.set_item_height('drawing_frame', h)
dpg.show_item('drawing_frame')
def mouse_release_callback():
if not get_height_map_file_path():
return
if not dpg.is_item_focused('map_child_window'):
return
coords = dpg.get_drawing_mouse_pos()
if get_current_action() == 'erase':
draw_rectangle(coords, 0)
elif get_current_action() == 'draw_rect':
layer = dpg.get_value('layer')
if layer == 'roads':
height = 1.
else:
height = dpg.get_value('height_input')
draw_rectangle(coords, height)
update_texture()
set_map_window_value('drawing', False)
dpg.hide_item('drawing_frame')
def mouse_click_callback():
if not get_height_map_file_path():
return
if not get_config_file_path():
return
if dpg.is_item_visible('emission_settings_window'):
dpg.hide_item('emission_settings_window')
return
emission_points = get_emission_points()
x, y = dpg.get_drawing_mouse_pos()
is_pos_emission_point, n = is_mouse_pos_emission_point(x, y, emission_points)
if is_pos_emission_point:
for key in emission_points[n]:
dpg.set_value(f'emission_point_{key}', emission_points[n][key])
dpg.set_item_user_data('emission_settings_window', n)
dpg.set_item_pos('emission_settings_window', dpg.get_drawing_mouse_pos())
dpg.show_item('emission_settings_window')
else:
if 0 <= x < dpg.get_item_width('map_child_window') and 0 <= y < dpg.get_item_height('map_child_window'):
add_emission_point_and_update_ui(x, y)
update_texture()
def draw_rectangle(coords, height):
y1, y2, x1, x2 = get_rect(get_prev_coords(), coords)
map_type = f'{dpg.get_value('layer')}_map'
height_map = get_map_window_value(map_type)
height_map[y1:y2, x1:x2] = height
set_map_window_value(map_type, height_map)
def is_point_in_triangle(x1, y1, x2, y2, x3, y3, x, y):
denominator = ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3))
a = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / denominator
b = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / denominator
c = 1 - a - b
return 0 <= a <= 1 and 0 <= b <= 1 and 0 <= c <= 1
def is_mouse_pos_emission_point(posx, posy, emission_points, side=30):
h = (3 ** 0.5 / 2) * side
for n in emission_points:
x = emission_points[n]['xpos']
y = emission_points[n]['ypos']
x1, y1 = x, y - (2 / 3) * h
x2, y2 = x + side / 2, y + (1 / 3) * h
x3, y3 = x - side / 2, y + (1 / 3) * h
if is_point_in_triangle(x1, y1, x2, y2, x3, y3, posx, posy):
return True, n
return False, 0
def get_triangle_coords(x, y, side=30):
h = (3 ** 0.5 / 2) * side
x1, y1 = x, y - (2 / 3) * h
x2, y2 = x + side / 2, y + (1 / 3) * h
x3, y3 = x - side / 2, y + (1 / 3) * h
return (x1, y1), (x2, y2), (x3, y3)