diff --git a/src/fluency/main.py b/src/fluency/main.py index a8c28c7..fb15d29 100644 --- a/src/fluency/main.py +++ b/src/fluency/main.py @@ -8,8 +8,12 @@ with a modern pygfx-based 3D renderer. import sys import math import uuid +import logging from typing import Optional, List, Dict, Any, Tuple 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 ( QApplication, QMainWindow, @@ -325,6 +329,9 @@ class Sketch2DWidget(QWidget): def mousePressEvent(self, event): 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: self._panning = True @@ -333,6 +340,7 @@ class Sketch2DWidget(QWidget): return if event.button() == Qt.RightButton: + logger.debug("Right click - resetting mode") self._mode = None self._draw_buffer = [] self._dynamic_line_end = None @@ -347,6 +355,7 @@ class Sketch2DWidget(QWidget): world_snapped = ( 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": self._handle_line_click(world_snapped) @@ -398,14 +407,17 @@ class Sketch2DWidget(QWidget): self.update() def _handle_line_click(self, pos: QPoint): + logger.debug(f"Line click at ({pos.x()}, {pos.y()})") if not self._sketch: self._sketch = OCCSketch() + logger.debug("Created new OCCSketch") if not self._draw_buffer: point = self._sketch.add_point(pos.x(), pos.y()) point.is_construction = self._is_construct self._points.append(point) self._draw_buffer.append(pos) + logger.debug(f"Added first point, buffer size={len(self._draw_buffer)}") else: point = self._sketch.add_point(pos.x(), pos.y()) point.is_construction = self._is_construct @@ -414,6 +426,7 @@ class Sketch2DWidget(QWidget): if len(self._points) >= 2: line = self._sketch.add_line(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] @@ -653,9 +666,11 @@ class Viewer3DWidget(QWidget): self._pending_meshes: List[Tuple] = [] def showEvent(self, event): + logger.info("Viewer3DWidget showEvent - initializing renderer") if not self._initialized: self._renderer.initialize(self) self._initialized = True + logger.info(f"Renderer initialized, pending meshes: {len(self._pending_meshes)}") for args in self._pending_meshes: self.add_mesh(*args) self._pending_meshes.clear() @@ -663,6 +678,7 @@ class Viewer3DWidget(QWidget): def _ensure_initialized(self): if not self._initialized: + logger.debug("Ensuring renderer is initialized") self._renderer.initialize(self) self._initialized = True @@ -670,14 +686,19 @@ class Viewer3DWidget(QWidget): return self._renderer 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: 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)}" self._ensure_initialized() mesh_id = self._renderer.add_mesh(vertices, faces, color, name) self._meshes[mesh_id] = {"vertices": vertices, "faces": faces, "name": name} self._renderer.render() + logger.info(f"Added mesh: {mesh_id}, name={name}") return mesh_id def update_mesh(self, mesh_id: str, vertices, faces): @@ -729,9 +750,11 @@ class MainWindow(QMainWindow): def __init__(self): super().__init__() + logger.info("Initializing MainWindow") self._project = Project() self._kernel = OCGeometryKernel() + logger.info("Created Project and OCGeometryKernel") self._current_component: Optional[Component] = None self._current_sketch: Optional[Sketch] = None @@ -743,6 +766,7 @@ class MainWindow(QMainWindow): self._setup_ui() self._setup_connections() self._create_initial_component() + logger.info("MainWindow initialization complete") def _setup_ui(self): self.setWindowTitle("Fluency CAD 2.0") @@ -1280,8 +1304,10 @@ class MainWindow(QMainWindow): return 0 def _new_component(self): + logger.info("=== NEW COMPONENT ===") comp = self._project.add_component() self._current_component = comp + logger.info(f"Created component: {comp.name}") btn = QPushButton(str(len(self._project.components))) btn.setCheckable(True) @@ -1365,19 +1391,27 @@ class MainWindow(QMainWindow): self.statusBar().showMessage("Flip workplane (not implemented)") def _add_sketch_to_component(self): + logger.info("=== ADD SKETCH TO COMPONENT ===") if not self._current_component: + logger.info("No current component, creating new one") self._current_component = self._project.add_component() 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: + logger.info("Creating new sketch in widget") sketch.occ_sketch = self._sketch_widget.create_sketch() self._current_sketch = sketch self._refresh_lists() self._sketch_widget.set_mode(None) self.statusBar().showMessage(f"Added sketch: {sketch.name}") + logger.info(f"=== SKETCH ADDED: {sketch.name} ===") def _edit_sketch(self): selected = self._sketch_list.currentItem() @@ -1430,13 +1464,18 @@ class MainWindow(QMainWindow): break def _extrude_sketch(self): + logger.info("=== EXTRUDE SKETCH ===") if not self._current_component: + logger.warning("No current component") return sketch = self._current_sketch + logger.debug(f"Current sketch: {sketch}") if not sketch or not sketch.occ_sketch: sketch_entity = self._sketch_widget.get_sketch() + logger.debug(f"Sketch from widget: {sketch_entity}") if not sketch_entity: + logger.warning("No sketch entity found") QMessageBox.warning(self, "No Sketch", "Please create a sketch first") return sketch.occ_sketch = sketch_entity @@ -1444,16 +1483,23 @@ class MainWindow(QMainWindow): dialog = ExtrudeDialog(self) if dialog.exec(): length, symmetric, invert, cut, union, rounded = dialog.get_values() + logger.info(f"Extrude params: length={length}, symmetric={symmetric}, invert={invert}") else: + logger.info("Extrude dialog cancelled") return try: + logger.debug("Getting geometry from sketch") geometry = sketch.occ_sketch.get_geometry() + logger.debug(f"Geometry: {geometry}") if not geometry: + logger.error("No geometry from sketch") QMessageBox.warning(self, "No Geometry", "Sketch has no valid geometry") return + logger.info("Calling kernel.extrude") body_geometry = self._kernel.extrude(geometry, length, symmetric=symmetric) + logger.debug(f"Body geometry created: {body_geometry}") body = self._current_component.add_body( Body( @@ -1463,15 +1509,23 @@ class MainWindow(QMainWindow): source_operation="extrude", ) ) + logger.info(f"Created body: {body.name}") + logger.debug("Getting mesh for body") 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) + logger.info(f"Render object: {body.render_object}") self._refresh_lists() self._viewer_3d.fit_camera() self.statusBar().showMessage(f"Extruded: {body.name}") + logger.info("=== EXTRUDE COMPLETE ===") except Exception as e: + logger.exception(f"Extrude failed: {e}") QMessageBox.critical(self, "Error", f"Extrude failed: {e}") def _revolve_sketch(self):