improve graph viewer UI and rendering
clear data before loading new file in graph viewer improve font load fix format
This commit is contained in:
@@ -172,6 +172,10 @@ class GraphViewer:
|
|||||||
np.sin(np.radians(self.pitch)),
|
np.sin(np.radians(self.pitch)),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not imgui.is_window_hovered():
|
||||||
|
return
|
||||||
|
|
||||||
if io.mouse_wheel != 0:
|
if io.mouse_wheel != 0:
|
||||||
self.move_speed += io.mouse_wheel * 0.05
|
self.move_speed += io.mouse_wheel * 0.05
|
||||||
self.move_speed = np.max([self.move_speed, 0.01])
|
self.move_speed = np.max([self.move_speed, 0.01])
|
||||||
@@ -502,6 +506,14 @@ class GraphViewer:
|
|||||||
def load_file(self, filepath: str):
|
def load_file(self, filepath: str):
|
||||||
"""Load a GraphML file with error handling"""
|
"""Load a GraphML file with error handling"""
|
||||||
try:
|
try:
|
||||||
|
# Clear existing data
|
||||||
|
self.id_node_map.clear()
|
||||||
|
self.nodes.clear()
|
||||||
|
self.selected_node = None
|
||||||
|
self.highlighted_node = None
|
||||||
|
self.setup_buffers()
|
||||||
|
|
||||||
|
# Load new graph
|
||||||
self.graph = nx.read_graphml(filepath)
|
self.graph = nx.read_graphml(filepath)
|
||||||
self.calculate_layout()
|
self.calculate_layout()
|
||||||
self.update_buffers()
|
self.update_buffers()
|
||||||
@@ -672,10 +684,6 @@ class GraphViewer:
|
|||||||
self.position, self.position + self.front, self.up
|
self.position, self.position + self.front, self.up
|
||||||
)
|
)
|
||||||
|
|
||||||
io = imgui.get_io()
|
|
||||||
self.window_width = int(io.display_size.x)
|
|
||||||
self.window_height = int(io.display_size.y)
|
|
||||||
|
|
||||||
aspect_ratio = self.window_width / self.window_height
|
aspect_ratio = self.window_width / self.window_height
|
||||||
self.proj_matrix = glm.perspective(
|
self.proj_matrix = glm.perspective(
|
||||||
glm.radians(60.0), # FOV
|
glm.radians(60.0), # FOV
|
||||||
@@ -839,7 +847,7 @@ class GraphViewer:
|
|||||||
def render(self):
|
def render(self):
|
||||||
"""Render the graph"""
|
"""Render the graph"""
|
||||||
# Clear screen
|
# Clear screen
|
||||||
self.glctx.clear(*self.background_color)
|
self.glctx.clear(*self.background_color, depth=1)
|
||||||
|
|
||||||
if not self.graph:
|
if not self.graph:
|
||||||
return
|
return
|
||||||
@@ -886,11 +894,15 @@ class GraphViewer:
|
|||||||
# Render id map
|
# Render id map
|
||||||
self.render_id_map(mvp)
|
self.render_id_map(mvp)
|
||||||
|
|
||||||
|
def render_labels(self):
|
||||||
# Render labels if enabled
|
# Render labels if enabled
|
||||||
if self.show_labels:
|
if self.show_labels and self.nodes:
|
||||||
# Save current font scale
|
# Save current font scale
|
||||||
original_scale = imgui.get_font_size()
|
original_scale = imgui.get_font_size()
|
||||||
|
|
||||||
|
self.update_view_proj_matrix()
|
||||||
|
mvp = self.proj_matrix * self.view_matrix
|
||||||
|
|
||||||
for node in self.nodes:
|
for node in self.nodes:
|
||||||
# Project node position to screen space
|
# Project node position to screen space
|
||||||
pos = mvp * glm.vec4(
|
pos = mvp * glm.vec4(
|
||||||
@@ -1013,13 +1025,39 @@ def create_sphere(sectors: int = 32, rings: int = 16) -> Tuple:
|
|||||||
return (vbo_vertices, vbo_elements)
|
return (vbo_vertices, vbo_elements)
|
||||||
|
|
||||||
|
|
||||||
|
def draw_text_with_bg(
|
||||||
|
text: str,
|
||||||
|
text_pos: imgui.ImVec2Like,
|
||||||
|
text_size: imgui.ImVec2Like,
|
||||||
|
bg_color: int,
|
||||||
|
):
|
||||||
|
imgui.get_window_draw_list().add_rect_filled(
|
||||||
|
(text_pos[0] - 5, text_pos[1] - 5),
|
||||||
|
(text_pos[0] + text_size[0] + 5, text_pos[1] + text_size[1] + 5),
|
||||||
|
bg_color,
|
||||||
|
3.0,
|
||||||
|
)
|
||||||
|
imgui.set_cursor_pos(text_pos)
|
||||||
|
imgui.text(text)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main application entry point"""
|
"""Main application entry point"""
|
||||||
viewer = GraphViewer()
|
viewer = GraphViewer()
|
||||||
|
|
||||||
|
show_fps = True
|
||||||
|
text_bg_color = imgui.IM_COL32(0, 0, 0, 100)
|
||||||
|
|
||||||
def gui():
|
def gui():
|
||||||
if not viewer.initialized:
|
if not viewer.initialized:
|
||||||
viewer.setup()
|
viewer.setup()
|
||||||
|
# # Change the theme
|
||||||
|
# tweaked_theme = hello_imgui.get_runner_params().imgui_window_params.tweaked_theme
|
||||||
|
# tweaked_theme.theme = hello_imgui.ImGuiTheme_.darcula_darker
|
||||||
|
# hello_imgui.apply_tweaked_theme(tweaked_theme)
|
||||||
|
|
||||||
|
viewer.window_width = int(imgui.get_window_width())
|
||||||
|
viewer.window_height = int(imgui.get_window_height())
|
||||||
|
|
||||||
# Handle keyboard and mouse input
|
# Handle keyboard and mouse input
|
||||||
viewer.handle_keyboard_input()
|
viewer.handle_keyboard_input()
|
||||||
@@ -1089,11 +1127,34 @@ def main():
|
|||||||
# Render graph settings window
|
# Render graph settings window
|
||||||
viewer.render_settings()
|
viewer.render_settings()
|
||||||
|
|
||||||
window_bg_color.w = 0.0
|
# Render FPS
|
||||||
|
if show_fps:
|
||||||
|
imgui.set_window_font_scale(1)
|
||||||
|
fps_text = f"FPS: {hello_imgui.frame_rate():.1f}"
|
||||||
|
text_size = imgui.calc_text_size(fps_text)
|
||||||
|
cursor_pos = (10, viewer.window_height - text_size.y - 10)
|
||||||
|
draw_text_with_bg(fps_text, cursor_pos, text_size, text_bg_color)
|
||||||
|
|
||||||
|
# Render highlighted node ID
|
||||||
|
if viewer.highlighted_node:
|
||||||
|
imgui.set_window_font_scale(1)
|
||||||
|
node_text = f"Node ID: {viewer.highlighted_node.label}"
|
||||||
|
text_size = imgui.calc_text_size(node_text)
|
||||||
|
cursor_pos = (
|
||||||
|
viewer.window_width - text_size.x - 10,
|
||||||
|
viewer.window_height - text_size.y - 10,
|
||||||
|
)
|
||||||
|
draw_text_with_bg(node_text, cursor_pos, text_size, text_bg_color)
|
||||||
|
|
||||||
|
window_bg_color.w = 0
|
||||||
style.set_color_(imgui.Col_.window_bg.value, window_bg_color)
|
style.set_color_(imgui.Col_.window_bg.value, window_bg_color)
|
||||||
|
|
||||||
# Render the graph
|
# Render labels
|
||||||
viewer.render()
|
viewer.render_labels()
|
||||||
|
|
||||||
|
def custom_background():
|
||||||
|
if viewer.initialized:
|
||||||
|
viewer.render()
|
||||||
|
|
||||||
runner_params = hello_imgui.RunnerParams()
|
runner_params = hello_imgui.RunnerParams()
|
||||||
runner_params.app_window_params.window_geometry.size = (
|
runner_params.app_window_params.window_geometry.size = (
|
||||||
@@ -1102,29 +1163,32 @@ def main():
|
|||||||
)
|
)
|
||||||
runner_params.app_window_params.window_title = "3D GraphML Viewer"
|
runner_params.app_window_params.window_title = "3D GraphML Viewer"
|
||||||
runner_params.callbacks.show_gui = gui
|
runner_params.callbacks.show_gui = gui
|
||||||
addons = immapp.AddOnsParams()
|
runner_params.callbacks.custom_background = custom_background
|
||||||
addons.with_markdown = True
|
|
||||||
|
|
||||||
def load_font():
|
def load_font():
|
||||||
io = imgui.get_io()
|
|
||||||
io.fonts.add_font_default()
|
|
||||||
|
|
||||||
# Load font for Chinese character support
|
|
||||||
# You will need to provide it yourself, or use another font.
|
# You will need to provide it yourself, or use another font.
|
||||||
font_filename = CUSTOM_FONT
|
font_filename = CUSTOM_FONT
|
||||||
|
|
||||||
if not os.path.exists("assets/" + font_filename):
|
use_custom_font = False
|
||||||
return
|
if not hello_imgui.asset_exists(font_filename):
|
||||||
|
asset_dir = os.path.join(os.path.dirname(__file__), "assets")
|
||||||
|
if os.path.isfile(os.path.join(asset_dir, font_filename)):
|
||||||
|
hello_imgui.set_assets_folder(asset_dir)
|
||||||
|
use_custom_font = True
|
||||||
|
|
||||||
# Get the full Chinese character range for ImGui
|
io = imgui.get_io()
|
||||||
# This includes all Chinese characters supported by ImGui
|
io.fonts.tex_desired_width = 4096 # Larger texture for better CJK font quality
|
||||||
cn_glyph_ranges_imgui = imgui.get_io().fonts.get_glyph_ranges_chinese_full()
|
|
||||||
|
if not use_custom_font:
|
||||||
|
io.fonts.add_font_default()
|
||||||
|
return
|
||||||
|
|
||||||
# Set up font loading parameters with Chinese character support
|
# Set up font loading parameters with Chinese character support
|
||||||
font_loading_params = hello_imgui.FontLoadingParams()
|
font_loading_params = hello_imgui.FontLoadingParams()
|
||||||
font_loading_params.glyph_ranges = hello_imgui.translate_common_glyph_ranges(
|
font_loading_params.glyph_ranges = hello_imgui.translate_common_glyph_ranges(
|
||||||
cn_glyph_ranges_imgui
|
imgui.get_io().fonts.get_glyph_ranges_chinese_full()
|
||||||
)
|
)
|
||||||
|
|
||||||
custom_font = hello_imgui.load_font(font_filename, 16.0, font_loading_params)
|
custom_font = hello_imgui.load_font(font_filename, 16.0, font_loading_params)
|
||||||
|
|
||||||
# # Merge with default font
|
# # Merge with default font
|
||||||
@@ -1137,12 +1201,11 @@ def main():
|
|||||||
# glyph_ranges_as_int_list=cn_glyph_ranges_imgui,
|
# glyph_ranges_as_int_list=cn_glyph_ranges_imgui,
|
||||||
# )
|
# )
|
||||||
|
|
||||||
io.fonts.tex_desired_width = 4096 # Larger texture for better CJK font quality
|
|
||||||
io.font_default = custom_font
|
io.font_default = custom_font
|
||||||
|
|
||||||
runner_params.callbacks.load_additional_fonts = load_font
|
runner_params.callbacks.load_additional_fonts = load_font
|
||||||
|
|
||||||
immapp.run(runner_params, addons)
|
immapp.run(runner_params)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Reference in New Issue
Block a user