feat: add CLI logging for debugging

- Add logging module with DEBUG level
- Log MainWindow initialization
- Log Viewer3DWidget initialization and mesh operations
- Log mouse events in Sketch2DWidget
- Log extrude operations with detailed steps
- Log component and sketch management
This commit is contained in:
bklronin
2026-03-14 09:01:20 +01:00
parent daed79dac6
commit d7ebbf45d5
+55 -1
View File
@@ -8,8 +8,12 @@ with a modern pygfx-based 3D renderer.
import sys import sys
import math import math
import uuid import uuid
import logging
from typing import Optional, List, Dict, Any, Tuple from typing import Optional, List, Dict, Any, Tuple
from dataclasses import dataclass, field from dataclasses import dataclass, field
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QApplication, QApplication,
QMainWindow, QMainWindow,
@@ -325,6 +329,9 @@ class Sketch2DWidget(QWidget):
def mousePressEvent(self, event): def mousePressEvent(self, event):
world_pos = self._screen_to_world(event.pos()) world_pos = self._screen_to_world(event.pos())
logger.debug(
f"Mouse press: button={event.button()}, mode={self._mode}, world_pos=({world_pos.x()}, {world_pos.y()})"
)
if event.button() == Qt.MiddleButton: if event.button() == Qt.MiddleButton:
self._panning = True self._panning = True
@@ -333,6 +340,7 @@ class Sketch2DWidget(QWidget):
return return
if event.button() == Qt.RightButton: if event.button() == Qt.RightButton:
logger.debug("Right click - resetting mode")
self._mode = None self._mode = None
self._draw_buffer = [] self._draw_buffer = []
self._dynamic_line_end = None self._dynamic_line_end = None
@@ -347,6 +355,7 @@ class Sketch2DWidget(QWidget):
world_snapped = ( world_snapped = (
self._screen_to_world(snapped_pos) if snapped_pos != event.pos() else world_pos self._screen_to_world(snapped_pos) if snapped_pos != event.pos() else world_pos
) )
logger.debug(f"Left click - mode={self._mode}, snapped={snapped_pos != event.pos()}")
if self._mode == "line": if self._mode == "line":
self._handle_line_click(world_snapped) self._handle_line_click(world_snapped)
@@ -398,14 +407,17 @@ class Sketch2DWidget(QWidget):
self.update() self.update()
def _handle_line_click(self, pos: QPoint): def _handle_line_click(self, pos: QPoint):
logger.debug(f"Line click at ({pos.x()}, {pos.y()})")
if not self._sketch: if not self._sketch:
self._sketch = OCCSketch() self._sketch = OCCSketch()
logger.debug("Created new OCCSketch")
if not self._draw_buffer: if not self._draw_buffer:
point = self._sketch.add_point(pos.x(), pos.y()) point = self._sketch.add_point(pos.x(), pos.y())
point.is_construction = self._is_construct point.is_construction = self._is_construct
self._points.append(point) self._points.append(point)
self._draw_buffer.append(pos) self._draw_buffer.append(pos)
logger.debug(f"Added first point, buffer size={len(self._draw_buffer)}")
else: else:
point = self._sketch.add_point(pos.x(), pos.y()) point = self._sketch.add_point(pos.x(), pos.y())
point.is_construction = self._is_construct point.is_construction = self._is_construct
@@ -414,6 +426,7 @@ class Sketch2DWidget(QWidget):
if len(self._points) >= 2: if len(self._points) >= 2:
line = self._sketch.add_line(self._points[-2], self._points[-1]) line = self._sketch.add_line(self._points[-2], self._points[-1])
self._lines.append((self._points[-2], self._points[-1])) self._lines.append((self._points[-2], self._points[-1]))
logger.debug(f"Added line between points, total lines={len(self._lines)}")
self._draw_buffer = [pos] self._draw_buffer = [pos]
@@ -653,9 +666,11 @@ class Viewer3DWidget(QWidget):
self._pending_meshes: List[Tuple] = [] self._pending_meshes: List[Tuple] = []
def showEvent(self, event): def showEvent(self, event):
logger.info("Viewer3DWidget showEvent - initializing renderer")
if not self._initialized: if not self._initialized:
self._renderer.initialize(self) self._renderer.initialize(self)
self._initialized = True self._initialized = True
logger.info(f"Renderer initialized, pending meshes: {len(self._pending_meshes)}")
for args in self._pending_meshes: for args in self._pending_meshes:
self.add_mesh(*args) self.add_mesh(*args)
self._pending_meshes.clear() self._pending_meshes.clear()
@@ -663,6 +678,7 @@ class Viewer3DWidget(QWidget):
def _ensure_initialized(self): def _ensure_initialized(self):
if not self._initialized: if not self._initialized:
logger.debug("Ensuring renderer is initialized")
self._renderer.initialize(self) self._renderer.initialize(self)
self._initialized = True self._initialized = True
@@ -670,14 +686,19 @@ class Viewer3DWidget(QWidget):
return self._renderer return self._renderer
def add_mesh(self, vertices, faces, color=None, name=None) -> str: def add_mesh(self, vertices, faces, color=None, name=None) -> str:
logger.debug(
f"add_mesh called: initialized={self._initialized}, vertices={len(vertices)}, faces={len(faces)}, name={name}"
)
if not self._initialized: if not self._initialized:
self._pending_meshes.append((vertices, faces, color, name)) self._pending_meshes.append((vertices, faces, color, name))
logger.info(f"Queued pending mesh, total pending: {len(self._pending_meshes)}")
return f"pending_{len(self._pending_meshes)}" return f"pending_{len(self._pending_meshes)}"
self._ensure_initialized() self._ensure_initialized()
mesh_id = self._renderer.add_mesh(vertices, faces, color, name) mesh_id = self._renderer.add_mesh(vertices, faces, color, name)
self._meshes[mesh_id] = {"vertices": vertices, "faces": faces, "name": name} self._meshes[mesh_id] = {"vertices": vertices, "faces": faces, "name": name}
self._renderer.render() self._renderer.render()
logger.info(f"Added mesh: {mesh_id}, name={name}")
return mesh_id return mesh_id
def update_mesh(self, mesh_id: str, vertices, faces): def update_mesh(self, mesh_id: str, vertices, faces):
@@ -729,9 +750,11 @@ class MainWindow(QMainWindow):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
logger.info("Initializing MainWindow")
self._project = Project() self._project = Project()
self._kernel = OCGeometryKernel() self._kernel = OCGeometryKernel()
logger.info("Created Project and OCGeometryKernel")
self._current_component: Optional[Component] = None self._current_component: Optional[Component] = None
self._current_sketch: Optional[Sketch] = None self._current_sketch: Optional[Sketch] = None
@@ -743,6 +766,7 @@ class MainWindow(QMainWindow):
self._setup_ui() self._setup_ui()
self._setup_connections() self._setup_connections()
self._create_initial_component() self._create_initial_component()
logger.info("MainWindow initialization complete")
def _setup_ui(self): def _setup_ui(self):
self.setWindowTitle("Fluency CAD 2.0") self.setWindowTitle("Fluency CAD 2.0")
@@ -1280,8 +1304,10 @@ class MainWindow(QMainWindow):
return 0 return 0
def _new_component(self): def _new_component(self):
logger.info("=== NEW COMPONENT ===")
comp = self._project.add_component() comp = self._project.add_component()
self._current_component = comp self._current_component = comp
logger.info(f"Created component: {comp.name}")
btn = QPushButton(str(len(self._project.components))) btn = QPushButton(str(len(self._project.components)))
btn.setCheckable(True) btn.setCheckable(True)
@@ -1365,19 +1391,27 @@ class MainWindow(QMainWindow):
self.statusBar().showMessage("Flip workplane (not implemented)") self.statusBar().showMessage("Flip workplane (not implemented)")
def _add_sketch_to_component(self): def _add_sketch_to_component(self):
logger.info("=== ADD SKETCH TO COMPONENT ===")
if not self._current_component: if not self._current_component:
logger.info("No current component, creating new one")
self._current_component = self._project.add_component() self._current_component = self._project.add_component()
sketch = self._current_component.add_sketch() sketch = self._current_component.add_sketch()
sketch.occ_sketch = self._sketch_widget.get_sketch() logger.debug(f"Created sketch: {sketch.name}")
sketch_widget_sketch = self._sketch_widget.get_sketch()
logger.debug(f"Sketch from widget: {sketch_widget_sketch}")
sketch.occ_sketch = sketch_widget_sketch
if not sketch.occ_sketch: if not sketch.occ_sketch:
logger.info("Creating new sketch in widget")
sketch.occ_sketch = self._sketch_widget.create_sketch() sketch.occ_sketch = self._sketch_widget.create_sketch()
self._current_sketch = sketch self._current_sketch = sketch
self._refresh_lists() self._refresh_lists()
self._sketch_widget.set_mode(None) self._sketch_widget.set_mode(None)
self.statusBar().showMessage(f"Added sketch: {sketch.name}") self.statusBar().showMessage(f"Added sketch: {sketch.name}")
logger.info(f"=== SKETCH ADDED: {sketch.name} ===")
def _edit_sketch(self): def _edit_sketch(self):
selected = self._sketch_list.currentItem() selected = self._sketch_list.currentItem()
@@ -1430,13 +1464,18 @@ class MainWindow(QMainWindow):
break break
def _extrude_sketch(self): def _extrude_sketch(self):
logger.info("=== EXTRUDE SKETCH ===")
if not self._current_component: if not self._current_component:
logger.warning("No current component")
return return
sketch = self._current_sketch sketch = self._current_sketch
logger.debug(f"Current sketch: {sketch}")
if not sketch or not sketch.occ_sketch: if not sketch or not sketch.occ_sketch:
sketch_entity = self._sketch_widget.get_sketch() sketch_entity = self._sketch_widget.get_sketch()
logger.debug(f"Sketch from widget: {sketch_entity}")
if not sketch_entity: if not sketch_entity:
logger.warning("No sketch entity found")
QMessageBox.warning(self, "No Sketch", "Please create a sketch first") QMessageBox.warning(self, "No Sketch", "Please create a sketch first")
return return
sketch.occ_sketch = sketch_entity sketch.occ_sketch = sketch_entity
@@ -1444,16 +1483,23 @@ class MainWindow(QMainWindow):
dialog = ExtrudeDialog(self) dialog = ExtrudeDialog(self)
if dialog.exec(): if dialog.exec():
length, symmetric, invert, cut, union, rounded = dialog.get_values() length, symmetric, invert, cut, union, rounded = dialog.get_values()
logger.info(f"Extrude params: length={length}, symmetric={symmetric}, invert={invert}")
else: else:
logger.info("Extrude dialog cancelled")
return return
try: try:
logger.debug("Getting geometry from sketch")
geometry = sketch.occ_sketch.get_geometry() geometry = sketch.occ_sketch.get_geometry()
logger.debug(f"Geometry: {geometry}")
if not geometry: if not geometry:
logger.error("No geometry from sketch")
QMessageBox.warning(self, "No Geometry", "Sketch has no valid geometry") QMessageBox.warning(self, "No Geometry", "Sketch has no valid geometry")
return return
logger.info("Calling kernel.extrude")
body_geometry = self._kernel.extrude(geometry, length, symmetric=symmetric) body_geometry = self._kernel.extrude(geometry, length, symmetric=symmetric)
logger.debug(f"Body geometry created: {body_geometry}")
body = self._current_component.add_body( body = self._current_component.add_body(
Body( Body(
@@ -1463,15 +1509,23 @@ class MainWindow(QMainWindow):
source_operation="extrude", source_operation="extrude",
) )
) )
logger.info(f"Created body: {body.name}")
logger.debug("Getting mesh for body")
vertices, faces = body.get_mesh(self._kernel) vertices, faces = body.get_mesh(self._kernel)
logger.info(f"Mesh: {len(vertices)} vertices, {len(faces)} faces")
logger.debug("Adding mesh to viewer")
body.render_object = self._viewer_3d.add_mesh(vertices, faces, body.color, body.name) body.render_object = self._viewer_3d.add_mesh(vertices, faces, body.color, body.name)
logger.info(f"Render object: {body.render_object}")
self._refresh_lists() self._refresh_lists()
self._viewer_3d.fit_camera() self._viewer_3d.fit_camera()
self.statusBar().showMessage(f"Extruded: {body.name}") self.statusBar().showMessage(f"Extruded: {body.name}")
logger.info("=== EXTRUDE COMPLETE ===")
except Exception as e: except Exception as e:
logger.exception(f"Extrude failed: {e}")
QMessageBox.critical(self, "Error", f"Extrude failed: {e}") QMessageBox.critical(self, "Error", f"Extrude failed: {e}")
def _revolve_sketch(self): def _revolve_sketch(self):