Skip to content
Snippets Groups Projects
map_edit.py 5.72 KiB
Newer Older
  • Learn to ignore specific revisions
  • Maryshca's avatar
    Maryshca committed
    import dearpygui.dearpygui as dpg
    
    
    Maryshca's avatar
    Maryshca committed
    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
    
    Maryshca's avatar
    Maryshca committed
    
    def load_height_map(file_path):
    
    Maryshca's avatar
    Maryshca committed
        with open(file_path, "r", encoding='utf-8') as file:
    
    Maryshca's avatar
    Maryshca committed
            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
    
    Maryshca's avatar
    Maryshca committed
            data = height_map * get_map_window_value('max_height')
    
    Maryshca's avatar
    Maryshca committed
            file.write(f"{w} {h}\n")
    
    Maryshca's avatar
    Maryshca committed
            for row in data:
    
    Maryshca's avatar
    Maryshca committed
                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)
    
    Maryshca's avatar
    Maryshca committed
                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)
    
    Maryshca's avatar
    Maryshca committed
    
        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
    
    Maryshca's avatar
    Maryshca committed
            
    
    Maryshca's avatar
    Maryshca committed
        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
    
    
    Maryshca's avatar
    Maryshca committed
        if dpg.is_item_visible('emission_settings_window'):
            dpg.hide_item('emission_settings_window')
            return
    
    
    Maryshca's avatar
    Maryshca committed
        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:
    
    Maryshca's avatar
    Maryshca committed
            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')
    
    Maryshca's avatar
    Maryshca committed
        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)