Skip to content
Snippets Groups Projects
Commit bb4bd07f authored by Maryshca's avatar Maryshca
Browse files

v 2.0 init

parent f63d74cd
No related branches found
No related tags found
No related merge requests found
......@@ -2,12 +2,12 @@
## Как запустить?
`pip install dearpygui numpy`
`pip install dearpygui numpy paramiko scp python-dotenv`
`git clone http://tesla.parallel.ru/kuzmichovamary/gui.git`
`cd gui`
`python prerun.py` -- один раз (тут собирается `config-parser` ;)
`python prerun.py` один раз (тут собирается `config-parser` ;)
`python app.py`
\ No newline at end of file
......@@ -4,34 +4,17 @@ import sys
import dearpygui.dearpygui as dpg
import numpy as np
from dotenv import load_dotenv
from styles import GuiStyle, INDENT, SPACE, FONT_SIZE, ICON_PATH
from config import load_config, dump_config
from generator import LCZ
from utils import *
from static_ui import construct_ui
from constants import ICON_PATH
ctypes.windll.shcore.SetProcessDpiAwareness(1)
TABS_UI = 'tabs_ui'
COLLAPSING_HEADERS_UI = 'collapsing_headers_ui'
WIDGET_WIDTH = 300
XOFFSET = 300
LCZS = ['compact_high_rise', 'compact_low_rise', 'compact_mid_rise', 'heavy_industry', 'large_low_rise', 'lightweight_low_rise', 'open_high_rise', 'open_low_rise', 'open_mid_rise', 'sparsley_build']
UIS = [TABS_UI, COLLAPSING_HEADERS_UI]
load_dotenv()
class ConfigEditor:
def __init__(self):
self.config = dict()
self.config_file_path = str()
self.height_map = None
self.height_map_path = str()
self.current_action = None
self.prev_coords = None
self.drawing = False
if sys.platform.startswith('win'):
ctypes.windll.shcore.SetProcessDpiAwareness(1)
if __name__ == '__main__':
dpg.create_context()
dpg.create_viewport(
title='config file editor',
......@@ -41,366 +24,8 @@ class ConfigEditor:
dpg.setup_dearpygui()
dpg.show_viewport()
self.styles = GuiStyle()
self.construct_main_window_ui()
if self.config_file_path:
self.construct_config_ui()
def update_texture(self):
if not self.height_map_path:
return
max_height = np.max(self.height_map)
normalized_map = self.height_map / max_height
texture_data = normalized_map.flatten()
texture_data = np.tile(texture_data, (4, 1)).T.flatten()
texture_data.resize(800 * 800 * 4)
width, height = self.height_map.shape
dpg.set_value('heatmap_texture', texture_data)
def map_edit_window_on_close(self):
self.height_map = None
self.height_map_path = str()
self.current_action = None
self.prev_coords = None
self.drawing = False
def delete_config_ui_and_clear_aliases(self):
if dpg.does_item_exist(self.config_file_path):
if dpg.get_item_type(self.config_file_path) == 'mvAppItemType::mvChildWindow':
uuid = dpg.get_item_parent(dpg.get_item_parent(self.config_file_path))
dpg.delete_item(uuid)
else:
dpg.delete_item(self.config_file_path)
if dpg.does_alias_exist(self.config_file_path):
dpg.remove_alias(self.config_file_path)
for full_path in self.config:
for path in path_iter(full_path, prefix=self.config_file_path):
if dpg.does_alias_exist(path):
dpg.remove_alias(path)
def update_config_values(self):
for path in self.config:
if dpg.does_item_exist(f'{self.config_file_path}.{path}'):
self.config[path].value = dpg.get_value(f'{self.config_file_path}.{path}')
def manage_file(self, sender, sender_data, user_data):
file_path = sender_data['file_path_name']
if not file_path:
return
if user_data == 'open_config':
self.delete_config_ui_and_clear_aliases()
self.config_file_path = file_path
self.config = load_config(file_path)
self.construct_config_ui(dpg.get_item_user_data('ui'))
elif user_data == 'open_map':
self.height_map_path = file_path
self.height_map = load_height_map(file_path)
dpg.show_item('map_window')
self.update_texture()
elif user_data == 'save_as' or user_data == 'save':
self.update_config_values()
dump_config(self.config, file_path)
dpg.show_item('file_save_popup')
elif user_data == 'save_map_as' or user_data == 'save_map':
dump_map(self.height_map, file_path)
dpg.show_item('file_save_popup')
def generate_map(self, sender, sender_data, user_data):
self.height_map_path = 'lcz.txt'
self.height_map = LCZ(config_path=f'configs/{sender}.json').to_height_map()
dpg.show_item('map_window')
self.update_texture()
def set_file_path(self, sender, sender_data, user_data):
file_path = sender_data['file_path_name']
dpg.set_value(user_data, file_path)
def open_file_dialog(self, sender, sender_data, user_data):
dpg.show_item('file_dialog')
dpg.set_item_user_data('file_dialog', user_data)
def open_folder_dialog(self, sender, sender_data, user_data):
dpg.show_item('folder_dialog')
dpg.set_item_user_data('folder_dialog', user_data)
def set_action(self, action):
self.current_action = action
def check_coords(self, x, y, w, h):
mx, my = dpg.get_item_pos('map')
mw, mh = dpg.get_item_width('map'), dpg.get_item_height('map')
return mx <= x <= x + w <= mx + mw and my <= y <= y + h <= my + mh
def mouse_down_callback(self):
if not self.height_map_path:
return
if not self.drawing:
self.prev_coords = dpg.get_mouse_pos()
self.drawing = True
else:
x, y = dpg.get_mouse_pos()
px, py = self.prev_coords
y += dpg.get_text_size('edit map')[1] + 2 * SPACE + dpg.get_y_scroll('map_window')
py += dpg.get_text_size('edit map')[1] + 2 * SPACE + dpg.get_y_scroll('map_window')
x += dpg.get_x_scroll('map_window')
px += dpg.get_x_scroll('map_window')
w, h = abs(x - px), abs(y - py)
x, y = min(x, px), min(y, py)
if w > 0 and h > 0 and self.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(self):
coords = dpg.get_mouse_pos()
if self.current_action == 'erase':
self.draw_rectangle(coords, 0)
elif self.current_action == 'draw_rect':
height = dpg.get_value('height_input')
self.draw_rectangle(coords, np.max(self.height_map) * height)
self.update_texture()
self.drawing = False
dpg.hide_item('drawing_frame')
def draw_rectangle(self, coords, height):
y1, y2, x1, x2 = get_rect(self.prev_coords, coords)
self.height_map[y1:y2, x1:x2] = height
def run_on_lab_server(self):
pass
def construct_config_ui(self, ui):
if not self.config_file_path:
return
self.update_config_values()
self.delete_config_ui_and_clear_aliases()
if ui == TABS_UI:
self.construct_config_ui_tabs()
else:
self.construct_config_ui_collapsing_headers()
def construct_main_window_ui(self):
dpg.bind_font(self.styles.montserrat_font)
self.styles.apply_theme('orange')
with dpg.window(label='config file editor', tag='main'):
with dpg.menu_bar():
with dpg.menu(label='config'):
dpg.add_menu_item(label='open', callback=self.open_file_dialog, tag='open_btn', user_data='open_config')
dpg.add_menu_item(label='save', callback=lambda: self.manage_file('', {'file_path_name': self.config_file_path}, 'save'))
dpg.add_menu_item(label='save as', callback=self.open_file_dialog, tag='save_as_btn', user_data='save_as')
with dpg.menu(label='map'):
dpg.add_menu_item(label='open map', callback=self.open_file_dialog, tag='open_map_btn', user_data='open_map')
with dpg.menu(label='generate map'):
for lcz_type in LCZS:
dpg.add_menu_item(label=lcz_type, check=False, callback=combo_menu(self.generate_map), tag=lcz_type)
with dpg.menu(label='run'):
dpg.add_menu_item(label='run on lab server', callback=self.run_on_lab_server)
with dpg.menu(label='view'):
with dpg.menu(label='ui', tag='ui', user_data=COLLAPSING_HEADERS_UI):
for ui in UIS:
dpg.add_menu_item(label=ui, check=True, default_value=False, callback=combo_menu(lambda s, a, u: self.construct_config_ui(s)), tag=ui)
dpg.set_value(UIS[1], True)
construct_ui()
with dpg.menu(label='theme'):
for theme in self.styles.themes:
dpg.add_menu_item(label=theme, check=True, default_value=False, callback=combo_menu(lambda s, a, u: self.styles.apply_theme(s)), tag=theme)
dpg.set_value('orange', True)
dpg.add_menu_item(label='show theme editor', callback=dpg.show_style_editor)
with dpg.menu(label='settings'):
dpg.add_menu_item(label='show mouse coords', check=True, callback=lambda _, v: dpg.show_item('mouse') if v else dpg.hide_item('mouse'), default_value=False)
dpg.add_text('', tag='mouse', show=False)
with dpg.file_dialog(directory_selector=False, show=False, callback=self.manage_file, tag='file_dialog', width=600, height=400):
dpg.add_file_extension('.txt', color=(0, 255, 0, 255))
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
with dpg.file_dialog(directory_selector=True, show=False, callback=self.set_file_path, tag='folder_dialog', width=500, height=400):
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
with dpg.window(label='', autosize=True, no_resize=True, modal=True, tag='file_save_popup', show=False, pos=(40, 40)):
dpg.add_text('file saved successfully:)')
with dpg.item_handler_registry(tag='main_handler'):
dpg.add_item_resize_handler(callback=lambda: self.change_height(self.config_file_path))
dpg.bind_item_handler_registry('main', 'main_handler')
dpg.set_viewport_resize_callback(lambda: self.change_height(self.config_file_path))
with dpg.texture_registry():
dpg.add_dynamic_texture(800, 800, np.zeros((800, 800, 4), dtype=np.uint8), tag='heatmap_texture')
with dpg.theme() as item_theme:
with dpg.theme_component(dpg.mvAll):
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, (0, 0, 0, 0), category=dpg.mvThemeCat_Core)
dpg.add_theme_style(dpg.mvStyleVar_ChildRounding, 0, category=dpg.mvThemeCat_Core)
dpg.add_colormap_registry(label="colormap registry", tag="colormap_registry")
dpg.add_colormap(list(map(apply_tint, [[0, 0, 0], [100, 100, 100], [255, 255, 255]])), False, tag="colormap", parent="colormap_registry")
with dpg.window(label='edit map', tag='map_window', horizontal_scrollbar=True, show=False, width=600, height=400, pos=[20, 60], on_close=self.map_edit_window_on_close):
with dpg.menu_bar():
with dpg.menu(label='file'):
dpg.add_menu_item(label='save', callback=lambda: self.manage_file('', {'file_path_name': self.height_map_path}, 'save_map'))
dpg.add_menu_item(label='save as', callback=self.open_file_dialog, tag='save_map_as_btn', user_data='save_map_as')
with dpg.group(horizontal=True):
with dpg.group(width=200, tag='tools'):
dpg.add_button(label='erase', callback=lambda: self.set_action('erase'))
dpg.add_button(label='draw rectangle', callback=lambda: self.set_action('draw_rect'))
dpg.add_colormap_slider(tag='height_input')
dpg.bind_colormap(dpg.last_item(), "colormap")
dpg.add_image('heatmap_texture', tint_color=(0, 119, 200, 255), tag='map')
dpg.add_child_window(tag='drawing_frame', show=False, width=0, height=0)
dpg.bind_item_theme('drawing_frame', item_theme)
def clb(s, a, u):
dpg.set_value('mouse', str(a))
with dpg.handler_registry():
dpg.add_mouse_move_handler(callback=clb)
dpg.add_mouse_down_handler(callback=self.mouse_down_callback)
dpg.add_mouse_release_handler(callback=self.mouse_release_callback)
def construct_config_ui_collapsing_headers(self):
dpg.add_collapsing_header(label=self.config_file_path, parent='main', tag=self.config_file_path, indent=0, default_open=True)
for full_path in self.config:
namespaces = full_path.split('.')
parent = self.config_file_path
for level in range(len(namespaces) - 1):
path = self.config_file_path + '.' + '.'.join(namespaces[:level+1])
if not dpg.does_item_exist(path):
dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT)
parent = path
self.create_widget(full_path)
def construct_config_ui_tabs(self):
tab_bar_exists, tab_bar_uuid = does_tab_bar_child_exist('main')
if not tab_bar_exists:
tab_bar_uuid = dpg.add_tab_bar(parent='main')
tab_uuid = dpg.add_tab(label=self.config_file_path, parent=tab_bar_uuid)
dpg.add_child_window(parent=tab_uuid, tag=self.config_file_path, border=True, autosize_y=False, autosize_x=True)
dpg.set_item_user_data(self.config_file_path, 2 * SPACE)
for full_path in self.config:
namespaces = full_path.split('.')
parent = self.config_file_path
for level in range(len(namespaces) - 1):
path = self.config_file_path + '.' + '.'.join(namespaces[:level+1])
tab_bar_exists, tab_bar_uuid = does_tab_bar_child_exist(parent)
if not tab_bar_exists:
tab_bar_uuid = dpg.add_tab_bar(parent=parent, callback=lambda s, a: self.change_height(a))
dpg.set_item_user_data(parent, dpg.get_item_user_data(parent) + 4 * SPACE + FONT_SIZE)
if not dpg.does_item_exist(path):
tab_uuid = dpg.add_tab(label=namespaces[level], parent=tab_bar_uuid)
dpg.add_child_window(parent=tab_uuid, tag=path, border=True, autosize_y=False, autosize_x=True)
dpg.set_item_user_data(path, 2 * SPACE)
parent = path
self.create_widget(full_path)
def change_height(self, item):
if not dpg.does_item_exist(item):
return
if dpg.get_item_type(item) == 'mvAppItemType::mvChildWindow':
uuid = dpg.get_item_parent(item)
new_height = dpg.get_viewport_client_height() - get_absolute_y(uuid) - SPACE * get_item_level(item)
dpg.set_item_height(item, max(new_height, dpg.get_item_user_data(item)))
for child in dpg.get_item_children(item, 1):
self.change_height(child)
def create_widget(self, full_path):
tag = self.config_file_path + '.' + full_path
parent = '.'.join([self.config_file_path] + full_path.split('.')[:-1])
value = self.config[full_path].value
value_type = self.config[full_path].value_type
key = self.config[full_path].key
comment = self.config[full_path].comment
if dpg.get_value('use_tabs_ui') and parent != self.config_file_path and full_path != key:
dpg.set_item_user_data(parent, dpg.get_item_user_data(parent) + 2 * SPACE + FONT_SIZE + SPACE)
indent = INDENT
if dpg.get_value('use_tabs_ui'):
indent = 0
with dpg.group(horizontal=True, parent=parent, indent=indent, xoffset=XOFFSET):
if not comment:
dpg.add_text(key)
if value_type == 'BOOLEAN':
dpg.add_checkbox(default_value=value, tag=tag)
elif value_type == 'DOUBLE':
dpg.add_input_double(default_value=value, tag=tag, format='%.10f', width=WIDGET_WIDTH)
elif value_type == 'INT':
dpg.add_input_int(default_value=value, tag=tag, width=WIDGET_WIDTH)
elif 'dir' in key.lower() or 'file' in key.lower():
with dpg.group(horizontal=True):
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH)
dpg.add_button(label='...', callback=self.open_folder_dialog, user_data=tag)
else:
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH)
else:
dpg.add_text(key)
with dpg.group(horizontal=True, xoffset=WIDGET_WIDTH + 100):
if value_type == 'BOOLEAN':
dpg.add_checkbox(default_value=value, tag=tag)
elif value_type == 'DOUBLE':
dpg.add_input_double(default_value=value, tag=tag, format='%.10f', width=WIDGET_WIDTH)
elif value_type == 'INT':
dpg.add_input_int(default_value=value, tag=tag, width=WIDGET_WIDTH)
elif 'dir' in key.lower() or 'file' in key.lower():
with dpg.group(horizontal=True):
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH - 3 * SPACE - dpg.get_text_size('...')[0])
dpg.add_button(label='...', callback=self.open_folder_dialog, user_data=tag)
else:
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH)
dpg.add_text(comment, color=(255, 255, 255, 150))
def run(self):
dpg.set_primary_window('main', True)
dpg.start_dearpygui()
dpg.destroy_context()
\ No newline at end of file
if __name__ == '__main__':
app = ConfigEditor()
if len(sys.argv) > 1:
app.config_file_path = sys.argv[1]
app.config = load_config(sys.argv[1])
app.run()
\ No newline at end of file
import dearpygui.dearpygui as dpg
from utils import *
from remote_run import start_remote_execution
from styles import get_accent_color, apply_theme
from generator import LCZ
from config import load_config, dump_config
from dynamic_ui import construct_config_ui
def map_window_on_close_clb(s, a, u):
dpg.set_item_user_data('map_window', {'height_map': None, 'height_map_file_path': None, 'drawing': False, 'prev_coords': None, 'current_action': None})
def construct_config_ui_clb(s, a, u):
if not get_config_file_path():
return
delete_item_children_and_clear_aliases()
update_config_values()
construct_config_ui(get_config_file_path(), get_config())
def map_open_clb(s, a, u):
height_map_file_path = a['file_path_name']
height_map = load_height_map(height_map_file_path)
set_map_window_value('height_map', height_map)
set_map_window_value('height_map_file_path', height_map_file_path)
update_texture(height_map)
dpg.show_item('map_window')
def generate_map_clb(s, a, u):
height_map = LCZ(config_path=f'configs/{s}.json').to_height_map()
set_map_window_value('height_map', height_map)
set_map_window_value('height_map_file_path', 'lcz.txt')
update_texture(height_map)
dpg.show_item('map_window')
def map_save_clb(s, a, u):
dump_map(get_height_map(), get_height_map_file_path())
dpg.show_item('message_popup')
def map_save_as_clb(s, a, u):
dump_map(get_height_map(), a['file_path_name'])
dpg.show_item('message_popup')
def open_map_save_as_dialog_clb(s, a, u):
dpg.show_item('map_save_as')
def open_map_open_dialog_clb(s, a, u):
dpg.show_item('map_open')
def open_config_open_dialog_clb(s, a, u):
dpg.show_item('config_open')
def search_clb(s, data, u):
if not get_config_file_path():
return
if not data:
return
for path in get_config():
if data.lower() in path.split('.')[-1]:
dpg.set_y_scroll('main', dpg.get_item_pos('.'.join([get_config_file_path(), path.split('.')[0]]))[1])
for tag in path_iter(path, prefix=get_config_file_path()):
if dpg.get_value(COLLAPSING_HEADERS_UI) == True:
dpg.set_value(tag, True)
else:
dpg.set_value(dpg.get_item_parent(dpg.get_item_parent(tag)), dpg.get_item_parent(tag))
change_color_temporarily('.'.join([get_config_file_path(), path, 'text']), color=get_accent_color())
def remote_run_clb(s, a, u):
if not get_config_file_path():
show_status_text('no config.txt specified. cannot run.')
return
update_config_values()
dump_config(get_config(), 'tmp.txt')
dpg.show_item('login_modal')
def apply_theme_clb(s, a, u):
apply_theme(s)
def set_file_path_clb(s, a, u):
file_path = a['file_path_name']
dpg.set_value(u, file_path)
def show_config_search_window_clb(s, a, u):
dpg.show_item('search_popup')
def start_remote_execution_clb(s, a, u):
start_remote_execution(dpg.get_value('server_username'), dpg.get_value('server_password'), dpg.get_value('gitlab_username'), dpg.get_value('gitlab_password'))
def update_config_values():
config = get_config()
for path in config:
if dpg.does_item_exist(f'{get_config_file_path()}.{path}'):
config[path].value = dpg.get_value(f'{get_config_file_path()}.{path}')
set_main_window_value('config', config)
def config_save_as_clb(s, a, u):
update_config_values()
dump_config(get_config(), a['file_path_name'])
dpg.show_item('message_popup')
def config_open_clb(s, a, u):
delete_item_children_and_clear_aliases()
config_file_path = a['file_path_name']
config = load_config(config_file_path)
set_main_window_value('config', config)
set_main_window_value('config_file_path', config_file_path)
construct_config_ui(a['file_path_name'], config)
def config_save_clb(s, a, u):
update_config_values()
dump_config(get_config(), get_config_file_path())
dpg.show_item('message_popup')
def set_action_clb(s, a, u):
set_map_window_value('current_action', s)
def set_action_none_clb(s, a, u):
set_map_window_value('current_action', None)
def open_config_save_as_dialog_clb(s, a, u):
dpg.show_item('config_open')
\ No newline at end of file
import os
TABS_UI = 'tabs_ui'
COLLAPSING_HEADERS_UI = 'collapsing_headers_ui'
WIDGET_WIDTH = 300
XOFFSET = 300
LCZS = ['compact_high_rise', 'compact_low_rise', 'compact_mid_rise', 'heavy_industry', 'large_low_rise', 'lightweight_low_rise', 'open_high_rise', 'open_low_rise', 'open_mid_rise', 'sparsley_build']
UIS = [TABS_UI, COLLAPSING_HEADERS_UI]
FONT_PATH = os.path.join('fonts', 'Montserrat-Medium.ttf')
ICON_PATH = os.path.join('icons', 'icon.ico')
FONT_SIZE = 24
ACCENT_COLOR = (0, 119, 200, 100)
ROUNDING = 10
SPACE = 10
INDENT = 40
BORDER = 3
TEXT = (0, 1)
ACCENT = (5, 18, 19, 20, 15, 16, 35, 37, 34, 23, 22, 25, 26, 27, 28, 29, 10, 11, 12, 30, 31, 32, 49, 50)
PRIMARY = (2, 3, 39)
SECONDARY = (36, 33, 21, 24, 4, 7, 8, 9, 13, 14)
APPLY_ALPHA = (1, 22, 25, 31, 34, 16)
COLOR_TYPE_TO_DPG_ITEM = {'TEXT': (0, 1), 'PRIMARY': (2, 3, 39), 'SECONDARY': (36, 33, 21, 24, 4, 7, 8, 9, 13, 14), 'ACCENT': (5, 18, 19, 20, 15, 16, 35, 37, 34, 23, 22, 25, 26, 27, 28, 29, 10, 11, 12, 30, 31, 32, 49, 50)}
COLOR_TO_COLOR_TYPE = {0: 'TEXT', 1: 'TEXT', 2: 'PRIMARY', 3: 'PRIMARY', 39: 'PRIMARY', 36: 'SECONDARY', 21: 'SECONDARY', 24: 'SECONDARY', 4: 'SECONDARY', 7: 'SECONDARY', 8: 'SECONDARY', 9: 'SECONDARY', 13: 'SECONDARY', 33: 'SECONDARY', 14: 'SECONDARY', 35: 'ACCENT', 20: 'ACCENT', 37: 'ACCENT', 22: 'ACCENT', 23: 'ACCENT', 5: 'ACCENT', 25: 'ACCENT', 26: 'ACCENT', 27: 'ACCENT', 28: 'ACCENT', 29: 'ACCENT', 10: 'ACCENT', 30: 'ACCENT', 11: 'ACCENT', 31: 'ACCENT', 12: 'ACCENT', 32: 'ACCENT', 49: 'ACCENT', 34: 'ACCENT', 15: 'ACCENT', 50: 'ACCENT', 16: 'ACCENT', 18: 'ACCENT', 19: 'ACCENT', 1: 'TEXT'}
BLUE = {
'TEXT': (255, 255, 255, 255),
'PRIMARY': (37, 37, 38, 255),
'SECONDARY': (51, 51, 55, 255),
'ACCENT': (0, 119, 200, 153)
}
ORANGE = {
'TEXT': (255, 255, 255, 255),
'PRIMARY': (37, 37, 38, 255),
'SECONDARY': (51, 51, 55, 255),
'ACCENT': (251, 133, 0, 153)
}
THEMES = {
'blue': BLUE,
'orange': ORANGE
}
\ No newline at end of file
import dearpygui.dearpygui as dpg
from utils import *
from constants import *
def open_folder_dialog_clb(s, a, u):
dpg.show_item('set_folder_dialog')
dpg.set_item_user_data('set_folder_dialog', u)
def change_tab_bar_height_clb(s, a, u):
change_height(a)
def construct_config_ui(config_file_path, config):
if get_current_ui_type() == TABS_UI:
construct_config_ui_tabs(config_file_path, config)
else:
construct_config_ui_collapsing_headers(config_file_path, config)
def construct_config_ui_collapsing_headers(config_file_path, config):
dpg.add_collapsing_header(label=config_file_path, parent='main', tag=config_file_path, indent=0, default_open=True)
for full_path in config:
namespaces = full_path.split('.')
parent = config_file_path
for level in range(len(namespaces) - 1):
path = config_file_path + '.' + '.'.join(namespaces[:level+1])
if not dpg.does_item_exist(path):
dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT)
parent = path
create_widget(config_file_path, config, full_path)
def construct_config_ui_tabs(config_file_path, config):
tab_bar_exists, tab_bar_uuid = does_tab_bar_child_exist('main')
if not tab_bar_exists:
tab_bar_uuid = dpg.add_tab_bar(parent='main')
tab_uuid = dpg.add_tab(label=config_file_path, parent=tab_bar_uuid)
dpg.add_child_window(parent=tab_uuid, tag=config_file_path, border=True, autosize_y=False, autosize_x=True)
dpg.set_item_user_data(config_file_path, 2 * SPACE)
for full_path in config:
namespaces = full_path.split('.')
parent = config_file_path
for level in range(len(namespaces) - 1):
path = config_file_path + '.' + '.'.join(namespaces[:level+1])
tab_bar_exists, tab_bar_uuid = does_tab_bar_child_exist(parent)
if not tab_bar_exists:
tab_bar_uuid = dpg.add_tab_bar(parent=parent, callback=change_tab_bar_height_clb)
dpg.set_item_user_data(parent, dpg.get_item_user_data(parent) + 4 * SPACE + FONT_SIZE)
if not dpg.does_item_exist(path):
tab_uuid = dpg.add_tab(label=namespaces[level], parent=tab_bar_uuid)
dpg.add_child_window(parent=tab_uuid, tag=path, border=True, autosize_y=False, autosize_x=True)
dpg.set_item_user_data(path, 2 * SPACE)
parent = path
create_widget(config_file_path, config, full_path)
def create_widget(config_file_path, config, full_path):
tag = config_file_path + '.' + full_path
parent = '.'.join([config_file_path] + full_path.split('.')[:-1])
value = config[full_path].value
value_type = config[full_path].value_type
key = config[full_path].key
comment = config[full_path].comment
if dpg.get_value('use_tabs_ui') and parent != config_file_path and full_path != key:
dpg.set_item_user_data(parent, dpg.get_item_user_data(parent) + 2 * SPACE + FONT_SIZE + SPACE)
indent = INDENT
if dpg.get_value('use_tabs_ui'):
indent = 0
with dpg.group(horizontal=True, parent=parent, indent=indent, xoffset=XOFFSET):
if not comment:
dpg.add_text(key, tag=f'{tag}.text')
if value_type == 'BOOLEAN':
dpg.add_checkbox(default_value=value, tag=tag)
elif value_type == 'DOUBLE':
dpg.add_input_double(default_value=value, tag=tag, format='%.10f', width=WIDGET_WIDTH)
elif value_type == 'INT':
dpg.add_input_int(default_value=value, tag=tag, width=WIDGET_WIDTH)
elif 'dir' in key.lower() or 'file' in key.lower():
with dpg.group(horizontal=True):
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH)
dpg.add_button(label='...', callback=open_folder_dialog_clb, user_data=tag)
else:
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH)
else:
dpg.add_text(key, tag=f'{tag}.text')
with dpg.group(horizontal=True, xoffset=WIDGET_WIDTH + 100):
if value_type == 'BOOLEAN':
dpg.add_checkbox(default_value=value, tag=tag)
elif value_type == 'DOUBLE':
dpg.add_input_double(default_value=value, tag=tag, format='%.10f', width=WIDGET_WIDTH)
elif value_type == 'INT':
dpg.add_input_int(default_value=value, tag=tag, width=WIDGET_WIDTH)
elif 'dir' in key.lower() or 'file' in key.lower():
with dpg.group(horizontal=True):
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH - 3 * SPACE - dpg.get_text_size('...')[0])
dpg.add_button(label='...', callback=open_folder_dialog_clb, user_data=tag)
else:
dpg.add_input_text(default_value=value, tag=tag, width=WIDGET_WIDTH)
dpg.add_text(comment, color=(255, 255, 255, 150))
\ No newline at end of file
......@@ -256,8 +256,6 @@ class LCZ:
if __name__ == '__main__':
lcz_types = ['compact_high_rise', 'compact_mid_rise', 'compact_low_rise', 'open_high_rise', 'open_mid_rise', 'open_low_rise', 'lightweight_low_rise', 'large_low_rise', 'sparsley_build', 'heavy_industry']
#sys.argv.append('sparsley_build')
fig, axs = plt.subplots(2, 2, figsize=(10, 6))
lcz_type = "open_mid_rise"
......@@ -281,37 +279,3 @@ if __name__ == '__main__':
plt.savefig(f'{out_folder}/height_maps_mid_rise.png')
plt.show()
if False:#len(sys.argv) <= 1:
fig, axs = plt.subplots(2, 5, figsize=(16, 7))
for ax, lcz_type in zip(axs.flat, lcz_types):
print(lcz_type)
lcz = LCZ(config_path=f'configs/{lcz_type}.json', output_folder='v2')
# lcz.to_model_input_building(f'building_{fn}.txt')
# lcz.to_model_input_street(f'street_{fn}.txt')
# lcz.to_image(f'lcz_{lcz_type}_tree.png')
lcz.check_params()
height_map = lcz.to_height_map()
im = ax.imshow(height_map, cmap='viridis', origin='lower')
ax.set_title(lcz_type)
fig.colorbar(im, ax=ax, shrink=0.3)
plt.tight_layout()
plt.savefig('height_maps_main_road.png')
plt.show()
if len(sys.argv) > 1:
lcz_type = sys.argv[1]
if lcz_type not in lcz_types:
lcz_type = lcz_types[0]
lcz = LCZ(config_path=f'configs/{lcz_type}.json', output_folder='v2')
lcz.to_image(f'lcz_{lcz_type}_tree.png')
lcz.check_params()
import dearpygui.dearpygui as dpg
from utils import *
from callbacks import *
def mouse_down_callback():
if not get_height_map_path():
return
if not is_drawing():
set_map_window_value('prev_coords', dpg.get_mouse_pos())
set_map_window_value('drawing', True)
else:
x, y = dpg.get_mouse_pos()
px, py = get_prev_coords()
y += dpg.get_text_size('edit map')[1] + 2 * SPACE + dpg.get_y_scroll('map_window')
py += dpg.get_text_size('edit map')[1] + 2 * SPACE + dpg.get_y_scroll('map_window')
x += dpg.get_x_scroll('map_window')
px += dpg.get_x_scroll('map_window')
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_path():
return
coords = dpg.get_mouse_pos()
if get_current_action() == 'erase':
draw_rectangle(coords, 0)
elif get_current_action() == 'draw_rect':
height = dpg.get_value('height_input')
draw_rectangle(coords, np.max(get_height_map()) * height)
update_texture(get_height_map())
set_map_window_value('drawing', False)
dpg.hide_item('drawing_frame')
def draw_rectangle(coords, height):
y1, y2, x1, x2 = get_rect(get_prev_coords(), coords)
height_map = get_height_map()
height_map[y1:y2, x1:x2] = height
set_map_window_value('height_map', height_map)
def on_ctrl_o(sender, app_data):
if dpg.is_key_down(dpg.mvKey_Control) and dpg.is_key_down(dpg.mvKey_O):
dpg.show_item('config_open')
def on_ctrl_f(sender, app_data):
if dpg.is_key_down(dpg.mvKey_Control) and dpg.is_key_down(dpg.mvKey_F):
dpg.show_item('search_popup')
def on_ctrl_s(sender, app_data):
if dpg.is_key_down(dpg.mvKey_Control) and dpg.is_key_down(dpg.mvKey_Shift) and dpg.is_key_down(dpg.mvKey_S):
dpg.show_item('config_save_as')
elif dpg.is_key_down(dpg.mvKey_Control) and dpg.is_key_down(dpg.mvKey_S):
config_save_clb()
def change_height_():
dpg.set_item_pos('status_text', (dpg.get_item_width('main') - dpg.get_text_size(dpg.get_value('status_text'))[0] - 2 * SPACE, dpg.get_item_pos('status_text')[1]))
if get_config_file_path():
change_height(get_config_file_path())
def setup_handlers():
with dpg.handler_registry():
dpg.add_key_press_handler(key=dpg.mvKey_O, callback=on_ctrl_o)
dpg.add_key_press_handler(key=dpg.mvKey_F, callback=on_ctrl_f)
dpg.add_key_press_handler(key=dpg.mvKey_S, callback=on_ctrl_s)
with dpg.item_handler_registry(tag='main_handler'):
dpg.add_item_resize_handler(callback=change_height_)
dpg.bind_item_handler_registry('main', 'main_handler')
dpg.set_viewport_resize_callback(change_height_)
with dpg.item_handler_registry(tag='map_handler'):
dpg.add_item_resize_handler(callback=set_action_none_clb)
dpg.bind_item_handler_registry('map_window', 'map_handler')
with dpg.handler_registry():
dpg.add_mouse_down_handler(callback=mouse_down_callback)
dpg.add_mouse_release_handler(callback=mouse_release_callback)
\ No newline at end of file
import threading
import os
import re
import time
from scp import SCPClient
import dearpygui.dearpygui as dpg
import paramiko
from utils import show_status_text
HOST = "geophyslab.srcc.msu.ru"
REPOS = (
"git clone http://{username}:{password}@tesla.parallel.ru/emortikov/nselibx-common.git",
"git clone http://{username}:{password}@tesla.parallel.ru/emortikov/nselibx-wstgrid.git",
"git clone http://{username}:{password}@tesla.parallel.ru/emortikov/nse-gabls1-urban-les.git"
)
def run_on_remote_server(username, password, gitlab_username, gitlab_password):
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, username=username, password=password)
scp = SCPClient(ssh.get_transport())
scp.put("tmp.txt", "./tmp.txt")
commands = [
"mkdir run",
"cd ./run"
]
# for repo in REPOS:
# commands.append(repo.format(username=gitlab_username, password=gitlab_password))
commands += [
"cd ./nse-gabls1-urban-les/nse-gabls1-urban-les/",
#"chmod +x cpall.sh",
#"./cpall.sh ../../code",
"cd ../../code",
#"make -B MACHINE=local COMPILER=gnu",
"cp ../../tmp.txt ./config.txt",
"./nsenx"
]
commands = '; '.join(commands)
log = ''
stdin, stdout, stderr = ssh.exec_command(commands)
while not stdout.channel.exit_status_ready():
if stdout.channel.recv_ready():
output = stdout.channel.recv(512).decode()
update_progress(output)
log += '\n\n' + output
time.sleep(1)
output = stdout.read().decode()
dpg.set_value("progress_bar", 1.)
dpg.hide_item('loading')
log += '\n\n' + output
with open("log.txt", "w") as res_file:
res_file.write(output)
scp.close()
ssh.close()
show_status_text("success:) log written to log.txt.")
except Exception as e:
show_status_text(f"error: {str(e)}")
def update_progress(output):
if not re.findall(r'([0-9]+)%', output):
progress = 0.0
show_status_text(f"building model")
dpg.show_item('loading')
x, y = dpg.get_item_pos('status_text')
dpg.set_item_pos('loading', (x - 40, y))
else:
progress = int(re.findall(r'([0-9]+)%', output)[-1]) / 100
show_status_text('')
dpg.hide_item('loading')
dpg.set_value("progress_bar", progress)
def start_remote_execution(server_username, server_password, gitlab_username, gitlab_password):
dpg.configure_item("login_modal", show=False)
threading.Thread(target=run_on_remote_server, args=(server_username, server_password, gitlab_username, gitlab_password)).start()
import dearpygui.dearpygui as dpg
from utils import *
from constants import *
from styles import setup_fonts, setup_themes, apply_theme, get_accent_color
from handlers import setup_handlers
from callbacks import *
def construct_main_window_ui():
with dpg.window(label='config file editor', tag='main', user_data={'config': None, 'config_file_path': None}):
with dpg.menu_bar():
with dpg.menu(label='config'):
dpg.add_menu_item(label='open\t\t', shortcut='ctrl+o', callback=open_config_open_dialog_clb, tag='open_config_open_dialog')
dpg.add_menu_item(label='search\t\t', shortcut='ctrl+f', callback=show_config_search_window_clb, tag='show_config_search_window')
dpg.add_menu_item(label='save\t\t', shortcut='ctrl+s', callback=config_save_clb, tag='save_config')
dpg.add_menu_item(label='save as\t\t', shortcut='ctrl+shift+s', callback=open_config_save_as_dialog_clb, tag='open_config_save_as_dialog')
with dpg.menu(label='map'):
dpg.add_menu_item(label='open map', callback=open_map_open_dialog_clb, tag='open_map_open_dialog')
with dpg.menu(label='generate map'):
for lcz_type in LCZS:
dpg.add_menu_item(label=lcz_type, check=False, callback=combo_menu(generate_map_clb), tag=lcz_type)
with dpg.menu(label='run'):
dpg.add_menu_item(label='run on lab server', callback=remote_run_clb, tag='remote_run')
with dpg.menu(label='view'):
with dpg.menu(label='ui', tag='ui'):
for ui in UIS:
dpg.add_menu_item(label=ui, check=True, default_value=False, callback=combo_menu(construct_config_ui_clb), tag=ui)
dpg.set_value(UIS[1], True)
with dpg.menu(label='theme', tag='theme'):
for theme in THEMES:
dpg.add_menu_item(label=theme, check=True, default_value=False, callback=combo_menu(apply_theme_clb), tag=theme)
dpg.set_value('orange', True)
dpg.add_progress_bar(label='progress', default_value=0.0, tag='progress_bar', height=FONT_SIZE, width=200, pos=[dpg.get_viewport_width() // 2 - 100 + SPACE, SPACE])
dpg.add_text('', tag='status_text', show=True)
dpg.add_loading_indicator(style=1, color=(255, 255, 255, 255), thickness=2, radius=2, tag='loading', show=False)
def construct_crendentials_window():
with dpg.window(label='credentials', show=False, tag='login_modal', width=550, height=350):
dpg.add_input_text(label='server username', tag='server_username', password=False, default_value=os.getenv('SERVER_LOGIN', ''), width=300)
dpg.add_input_text(label='server password', tag='server_password', password=True, default_value=os.getenv('SERVER_PASS', ''), width=300)
dpg.add_input_text(label='gitlab username', tag='gitlab_username', password=False, default_value=os.getenv('GITLAB_LOGIN', ''), width=300)
dpg.add_input_text(label='gitlab password', tag='gitlab_password', password=True, default_value=os.getenv('GITLAB_PASS', ''), width=300)
dpg.add_button(label='submit', callback=start_remote_execution_clb)
def construct_config_open_dialog():
with dpg.file_dialog(directory_selector=False, show=False, callback=config_open_clb, tag='config_open', width=600, height=400):
dpg.add_file_extension('.txt', color=(0, 255, 0, 255))
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
def construct_config_save_as_dialog():
with dpg.file_dialog(directory_selector=False, show=False, callback=config_save_as_clb, tag='config_save_as', width=600, height=400):
dpg.add_file_extension('.txt', color=(0, 255, 0, 255))
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
def construct_map_open_dialog():
with dpg.file_dialog(directory_selector=False, show=False, callback=map_open_clb, tag='map_open', width=600, height=400):
dpg.add_file_extension('.txt', color=(0, 255, 0, 255))
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
def construct_map_save_as_dialog():
with dpg.file_dialog(directory_selector=False, show=False, callback=map_save_as_clb, tag='map_save_as', width=600, height=400):
dpg.add_file_extension('.txt', color=(0, 255, 0, 255))
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
def construct_set_file_path_dialog():
with dpg.file_dialog(directory_selector=True, show=False, callback=set_file_path_clb, tag='set_folder_dialog', width=500, height=400):
dpg.add_file_extension('.*', color=(255, 255, 255, 255))
def construct_message_window():
with dpg.window(label='', no_collapse=True, autosize=True, no_resize=True, modal=True, tag='message_popup', show=False, pos=(dpg.get_viewport_width() / 3, dpg.get_viewport_height() / 3)):
dpg.add_text('file saved successfully:)')
def construct_search_window():
with dpg.window(label='', no_collapse=True, autosize=True, no_resize=True, tag='search_popup', show=False, pos=(40, 40)):
dpg.add_input_text(hint='search for...', on_enter=True, callback=search_clb, tag='search')
def construct_map_edit_window():
with dpg.texture_registry():
dpg.add_dynamic_texture(800, 800, np.zeros((800, 800, 4), dtype=np.uint8), tag='heatmap_texture')
with dpg.theme() as item_theme:
with dpg.theme_component(dpg.mvAll):
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, (0, 0, 0, 0), category=dpg.mvThemeCat_Core)
dpg.add_theme_style(dpg.mvStyleVar_ChildRounding, 0, category=dpg.mvThemeCat_Core)
dpg.add_colormap_registry(label='colormap registry', tag='colormap_registry')
dpg.add_colormap(list(map(apply_tint, [[0, 0, 0], [100, 100, 100], [255, 255, 255]])), False, tag='colormap', parent='colormap_registry')
with dpg.window(label='edit map', tag='map_window', user_data={'height_map': None, 'height_map_file_path': None, 'drawing': False, 'prev_coords': None, 'current_action': None}, horizontal_scrollbar=True, show=False, width=600, height=400, pos=[20, 60], on_close=map_window_on_close_clb):
with dpg.menu_bar():
with dpg.menu(label='file'):
dpg.add_menu_item(label='save', callback=map_save_clb, tag='map_save')
dpg.add_menu_item(label='save as', callback=open_map_save_as_dialog_clb, tag='open_map_save_as_dialog')
with dpg.group(horizontal=True):
with dpg.group(width=200, tag='tools'):
dpg.add_button(label='erase', callback=set_action_clb, tag='erase')
dpg.add_button(label='draw rectangle', callback=set_action_clb, tag='draw_rect')
dpg.add_colormap_slider(tag='height_input')
dpg.bind_colormap(dpg.last_item(), 'colormap')
dpg.add_image('heatmap_texture', tint_color=(0, 119, 200, 255), tag='map')
dpg.add_child_window(tag='drawing_frame', show=False, width=0, height=0)
dpg.bind_item_theme('drawing_frame', item_theme)
def construct_ui():
construct_main_window_ui()
construct_message_window()
construct_map_open_dialog()
construct_map_save_as_dialog()
construct_map_edit_window()
construct_crendentials_window()
construct_config_save_as_dialog()
construct_config_open_dialog()
construct_search_window()
construct_set_file_path_dialog()
setup_handlers()
setup_fonts()
setup_themes()
\ No newline at end of file
import os
from enum import Enum
import dearpygui.dearpygui as dpg
FONT_PATH = "fonts\\Montserrat-Medium.ttf"
ICON_PATH = "icons\\icon.ico"
FONT_SIZE = 24
ACCENT_COLOR = (0, 119, 200, 100)
ROUNDING = 10
SPACE = 10
INDENT = 40
BORDER = 3
TEXT = (0, 1)
ACCENT = (5, 18, 19, 20, 15, 16, 35, 37, 34, 23, 22, 25, 26, 27, 28, 29, 10, 11, 12, 30, 31, 32, 49, 50)
PRIMARY = (2, 3, 39)
SECONDARY = (36, 33, 21, 24, 4, 7, 8, 9, 13, 14)
APPLY_ALPHA = (1, 22, 25, 31, 34, 16)
COLOR_TYPE_TO_DPG_ITEM = {'TEXT': (0, 1), 'PRIMARY': (2, 3, 39), 'SECONDARY': (36, 33, 21, 24, 4, 7, 8, 9, 13, 14), 'ACCENT': (5, 18, 19, 20, 15, 16, 35, 37, 34, 23, 22, 25, 26, 27, 28, 29, 10, 11, 12, 30, 31, 32, 49, 50)}
COLOR_TO_COLOR_TYPE = {0: 'TEXT', 1: 'TEXT', 2: 'PRIMARY', 3: 'PRIMARY', 39: 'PRIMARY', 36: 'SECONDARY', 21: 'SECONDARY', 24: 'SECONDARY', 4: 'SECONDARY', 7: 'SECONDARY', 8: 'SECONDARY', 9: 'SECONDARY', 13: 'SECONDARY', 33: 'SECONDARY', 14: 'SECONDARY', 35: 'ACCENT', 20: 'ACCENT', 37: 'ACCENT', 22: 'ACCENT', 23: 'ACCENT', 5: 'ACCENT', 25: 'ACCENT', 26: 'ACCENT', 27: 'ACCENT', 28: 'ACCENT', 29: 'ACCENT', 10: 'ACCENT', 30: 'ACCENT', 11: 'ACCENT', 31: 'ACCENT', 12: 'ACCENT', 32: 'ACCENT', 49: 'ACCENT', 34: 'ACCENT', 15: 'ACCENT', 50: 'ACCENT', 16: 'ACCENT', 18: 'ACCENT', 19: 'ACCENT', 1: 'TEXT'}
BLUE = {
'TEXT': (255, 255, 255, 255),
'PRIMARY': (37, 37, 38, 255),
'SECONDARY': (51, 51, 55, 255),
'ACCENT': (0, 119, 200, 153)
}
ORANGE = {
'TEXT': (255, 255, 255, 255),
'PRIMARY': (37, 37, 38, 255),
'SECONDARY': (51, 51, 55, 255),
'ACCENT': (251, 133, 0, 153)
}
from utils import *
from constants import *
def apply_alpha(color, divisor=2):
r, g, b, a = color
......@@ -76,31 +50,19 @@ def add_styles_to_theme(theme):
dpg.add_theme_style(dpg.mvStyleVar_FrameBorderSize, 0, category=dpg.mvThemeCat_Core)
class GuiStyle:
def __init__(self):
self.font_registry = dpg.add_font_registry()
self.montserrat_font = dpg.add_font(FONT_PATH, FONT_SIZE, parent=self.font_registry)
self.fonts = {
'montserrat': self.montserrat_font
}
self.themes = {
'blue': BLUE,
'orange': ORANGE
}
self.dpg_themes = dict()
def setup_fonts():
font_registry = dpg.add_font_registry()
montserrat_font = dpg.add_font(FONT_PATH, FONT_SIZE, parent=font_registry)
dpg.bind_font(montserrat_font)
for theme_name in self.themes:
def apply_theme(theme_name):
theme = dpg.add_theme()
add_styles_to_theme(theme)
add_colors_to_theme(self.themes[theme_name], theme)
self.dpg_themes[theme_name] = theme
add_colors_to_theme(THEMES[theme_name], theme)
dpg.bind_theme(theme)
def apply_font(self, font):
dpg.bind_font(self.fonts[font])
def setup_themes():
apply_theme(get_current_theme())
def apply_theme(self, theme):
print('appling', theme)
dpg.bind_theme(self.dpg_themes[theme])
\ No newline at end of file
def get_accent_color():
return THEMES[get_current_theme()]['ACCENT']
\ No newline at end of file
import dearpygui.dearpygui as dpg
import numpy as np
import threading
from styles import SPACE
from constants import *
def dump_map(height_map, file_path):
with open(file_path, "w", encoding="utf-8") as file:
w, h = height_map.shape
file.write(f"{w} {h}\n")
for row in height_map:
file.write(" ".join(list(map(str, row))) + "\n")
def get_current_ui_type():
for child in dpg.get_item_children('ui', 1):
if dpg.get_value(child):
return dpg.get_item_alias(child)
def get_current_theme():
for child in dpg.get_item_children('theme', 1):
if dpg.get_value(child):
return dpg.get_item_alias(child)
def get_config_file_path():
return dpg.get_item_user_data('main')['config_file_path']
def get_config():
return dpg.get_item_user_data('main')['config']
def set_main_window_value(key, value):
data = dpg.get_item_user_data('main')
data[key] = value
dpg.set_item_user_data('main', data)
def get_height_map_path():
return dpg.get_item_user_data('map_window')['height_map_file_path']
def get_height_map():
return dpg.get_item_user_data('map_window')['height_map']
def is_drawing():
return dpg.get_item_user_data('map_window')['drawing']
def get_prev_coords():
return dpg.get_item_user_data('map_window')['prev_coords']
def get_current_action():
return dpg.get_item_user_data('map_window')['current_action']
def set_map_window_value(key, value):
data = dpg.get_item_user_data('map_window')
data[key] = value
dpg.set_item_user_data('map_window', data)
def show_status_text(message):
dpg.set_item_pos('status_text', (dpg.get_item_width('main') - dpg.get_text_size(message)[0] - 2 * SPACE, dpg.get_item_pos('status_text')[1]))
dpg.set_value('status_text', message)
def path_iter(path, prefix=""):
namespaces = path.split('.')
for i in range(len(namespaces)):
yield prefix + '.' + '.'.join(namespaces[:i+1])
def delete_item_and_clear_alias(item):
alias = dpg.get_item_alias(item)
if alias:
dpg.remove_alias(alias)
if dpg.does_item_exist(item):
dpg.delete_item(item)
def delete_item_children_and_clear_aliases_(item):
if dpg.does_item_exist(item):
for child in dpg.get_item_children(item, 1):
delete_item_children_and_clear_aliases_(child)
delete_item_and_clear_alias(child)
def delete_item_children_and_clear_aliases():
if len(dpg.get_item_children('main', 1)) > 1:
delete_item_children_and_clear_aliases_(dpg.get_item_children('main', 1)[1])
delete_item_and_clear_alias(dpg.get_item_children('main', 1)[1])
####################################################################################
#
# search utils
#
####################################################################################
def change_color_temporarily(text_tag, color, duration=1):
color = list(color)[:-1] + [255]
dpg.configure_item(text_tag, color=color)
threading.Timer(duration, lambda: revert_color(text_tag)).start()
def revert_color(text_tag):
dpg.configure_item(text_tag, color=(255, 255, 255, 255))
####################################################################################
#
# edit map utils
#
####################################################################################
def update_texture(height_map):
max_height = np.max(height_map)
normalized_map = height_map / max_height
texture_data = normalized_map.flatten()
texture_data = np.tile(texture_data, (4, 1)).T.flatten()
texture_data.resize(800 * 800 * 4)
width, height = height_map.shape
dpg.set_value('heatmap_texture', texture_data)
def check_coords(x, y, w, h):
mx, my = dpg.get_item_pos('map')
mw, mh = dpg.get_item_width('map'), dpg.get_item_height('map')
return mx <= x <= x + w <= mx + mw and my <= y <= y + h <= my + mh
def apply_tint(color, tint=(0, 119, 200)):
tint = np.array(tint) / 255
......@@ -38,6 +140,42 @@ def load_height_map(file_path):
height_map = [list(map(int, line.strip().split())) for line in lines]
return np.array(height_map)
def dump_map(height_map, file_path):
with open(file_path, "w", encoding="utf-8") as file:
w, h = height_map.shape
file.write(f"{w} {h}\n")
for row in height_map:
file.write(" ".join(list(map(str, row))) + "\n")
####################################################################################
#
# main menu utils
#
####################################################################################
def combo_menu(callback):
def func(s, a, u):
for child in dpg.get_item_children(dpg.get_item_parent(s), 1):
if dpg.get_item_alias(child) != dpg.get_item_alias(s):
dpg.set_value(child, False)
else:
dpg.set_value(child, True)
dpg.set_item_user_data(s, dpg.get_item_alias(s))
callback(s, a, u)
return func
####################################################################################
#
# tabs ui utils
#
####################################################################################
def does_tab_bar_child_exist(item):
for uuid in dpg.get_item_children(item, 1):
if dpg.get_item_type(uuid) == "mvAppItemType::mvTabBar":
return True, uuid
return False, None
def get_absolute_y(item):
y = dpg.get_item_pos(item)[1]
parent = dpg.get_item_parent(item)
......@@ -56,24 +194,14 @@ def get_item_level(item):
parent = dpg.get_item_parent(parent)
return level
def does_tab_bar_child_exist(item):
for uuid in dpg.get_item_children(item, 1):
if dpg.get_item_type(uuid) == "mvAppItemType::mvTabBar":
return True, uuid
return False, None
def change_height(item):
if not dpg.does_item_exist(item):
return
if dpg.get_item_type(item) == 'mvAppItemType::mvChildWindow':
uuid = dpg.get_item_parent(item)
new_height = dpg.get_viewport_client_height() - get_absolute_y(uuid) - SPACE * get_item_level(item)
def path_iter(path, prefix=""):
namespaces = path.split('.')
for i in range(len(namespaces)):
yield prefix + '.' + '.'.join(namespaces[:i+1])
dpg.set_item_height(item, max(new_height, dpg.get_item_user_data(item)))
def combo_menu(callback):
def func(s, a, u):
for child in dpg.get_item_children(dpg.get_item_parent(s), 1):
if dpg.get_item_alias(child) != dpg.get_item_alias(s):
dpg.set_value(child, False)
else:
dpg.set_value(child, True)
dpg.set_item_user_data(s, dpg.get_item_alias(s))
callback(s, a, u)
return func
\ No newline at end of file
for child in dpg.get_item_children(item, 1):
change_height(child)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment