custom joint support
This commit is contained in:
+4
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"individual": [
|
"individual": [
|
||||||
{ "name": "Start Node", "type": "begin" },
|
{ "name": "New Event", "type": "begin" },
|
||||||
{
|
{
|
||||||
"name": "Average",
|
"name": "Average",
|
||||||
"type": "middle",
|
"type": "middle",
|
||||||
@@ -53,6 +53,8 @@
|
|||||||
{ "name": "Joint 14", "type": "logic" },
|
{ "name": "Joint 14", "type": "logic" },
|
||||||
{ "name": "Joint 15", "type": "logic" },
|
{ "name": "Joint 15", "type": "logic" },
|
||||||
{ "name": "Joint 16", "type": "logic" },
|
{ "name": "Joint 16", "type": "logic" },
|
||||||
{ "name": "Joint 17", "type": "logic" }
|
{ "name": "Joint 17", "type": "logic" },
|
||||||
|
{ "name": "New Calculated Joint", "type": "begin" }
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ import PySide6
|
|||||||
from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QFormLayout, QGraphicsItem, QGraphicsProxyWidget, QGraphicsTextItem, QLineEdit, QListWidget, QListWidgetItem, QMainWindow, QProgressDialog, QSizePolicy, QStyleOptionGraphicsItem, QTabBar, QWidget, QVBoxLayout, QGraphicsView, QGraphicsScene,
|
from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QFormLayout, QGraphicsItem, QGraphicsProxyWidget, QGraphicsTextItem, QLineEdit, QListWidget, QListWidgetItem, QMainWindow, QProgressDialog, QSizePolicy, QStyleOptionGraphicsItem, QTabBar, QWidget, QVBoxLayout, QGraphicsView, QGraphicsScene,
|
||||||
QHBoxLayout, QSplitter, QLabel, QPushButton, QComboBox, QInputDialog, QGraphicsRectItem,
|
QHBoxLayout, QSplitter, QLabel, QPushButton, QComboBox, QInputDialog, QGraphicsRectItem,
|
||||||
QFileDialog, QScrollArea, QMessageBox, QSlider, QTextEdit, QGroupBox, QGridLayout, QCheckBox, QTabWidget, QProgressBar)
|
QFileDialog, QScrollArea, QMessageBox, QSlider, QTextEdit, QGroupBox, QGridLayout, QCheckBox, QTabWidget, QProgressBar)
|
||||||
from PySide6.QtCore import QEvent, Qt, QThread, Signal, QUrl, QRectF, QPointF, QRect, QSizeF, QTimer
|
from PySide6.QtCore import QEvent, QObject, Qt, QThread, Signal, QUrl, QRectF, QPointF, QRect, QSizeF, QTimer
|
||||||
from PySide6.QtGui import QCursor, QDoubleValidator, QGuiApplication, QPainter, QColor, QFont, QPen, QBrush, QAction, QKeySequence, QIcon, QTextOption, QImage, QPixmap, QTransform
|
from PySide6.QtGui import QCursor, QDoubleValidator, QGuiApplication, QPainter, QColor, QFont, QPen, QBrush, QAction, QKeySequence, QIcon, QTextOption, QImage, QPixmap, QTransform
|
||||||
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
|
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
|
||||||
from PySide6.QtMultimediaWidgets import QGraphicsVideoItem
|
from PySide6.QtMultimediaWidgets import QGraphicsVideoItem
|
||||||
@@ -3162,10 +3162,17 @@ from PySide6.QtWidgets import QGraphicsPathItem, QGraphicsSimpleTextItem
|
|||||||
from PySide6.QtWidgets import QGraphicsItem, QGraphicsSimpleTextItem, QInputDialog
|
from PySide6.QtWidgets import QGraphicsItem, QGraphicsSimpleTextItem, QInputDialog
|
||||||
|
|
||||||
|
|
||||||
|
class BlockSignalProxy(QObject):
|
||||||
|
nameChanged = Signal(str, str)
|
||||||
|
|
||||||
class PuzzleBlock(QGraphicsPathItem):
|
class PuzzleBlock(QGraphicsPathItem):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, b_type, label, parent_item=None, fields=None):
|
def __init__(self, b_type, label, parent_item=None, fields=None):
|
||||||
super().__init__(parent_item)
|
super().__init__(parent_item)
|
||||||
|
|
||||||
|
self.signals = BlockSignalProxy()
|
||||||
|
|
||||||
self.b_type = b_type # "begin", "middle", "end"
|
self.b_type = b_type # "begin", "middle", "end"
|
||||||
self.label_text = label
|
self.label_text = label
|
||||||
self.width = 160
|
self.width = 160
|
||||||
@@ -3322,8 +3329,7 @@ class PuzzleBlock(QGraphicsPathItem):
|
|||||||
if self.b_type == "begin":
|
if self.b_type == "begin":
|
||||||
new_name, ok = QInputDialog.getText(None, "Rename Step", "Enter name:", text=self.label_text)
|
new_name, ok = QInputDialog.getText(None, "Rename Step", "Enter name:", text=self.label_text)
|
||||||
if ok and new_name:
|
if ok and new_name:
|
||||||
self.label_text = new_name
|
self.finish_rename(new_name)
|
||||||
self.label_item.setText(new_name)
|
|
||||||
super().mouseDoubleClickEvent(event)
|
super().mouseDoubleClickEvent(event)
|
||||||
|
|
||||||
|
|
||||||
@@ -3383,6 +3389,20 @@ class PuzzleBlock(QGraphicsPathItem):
|
|||||||
return super().itemChange(change, value)
|
return super().itemChange(change, value)
|
||||||
|
|
||||||
|
|
||||||
|
def finish_rename(self, new_text):
|
||||||
|
old_text = self.label_text
|
||||||
|
print(f"[DEBUG - Block] Renaming '{old_text}' to '{new_text}'")
|
||||||
|
|
||||||
|
self.label_text = new_text
|
||||||
|
if hasattr(self, 'label_item'):
|
||||||
|
self.label_item.setText(new_text)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
if self.b_type == "begin":
|
||||||
|
print(f"[DEBUG - Block] Emitting nameChanged signal...")
|
||||||
|
self.signals.nameChanged.emit(old_text, new_text)
|
||||||
|
|
||||||
|
|
||||||
class BlockLibrary(QListWidget):
|
class BlockLibrary(QListWidget):
|
||||||
def __init__(self, parent_tab, stringy):
|
def __init__(self, parent_tab, stringy):
|
||||||
@@ -3447,8 +3467,39 @@ class BlockLibrary(QListWidget):
|
|||||||
print(f"DEBUG: Drag finished with result: {result}")
|
print(f"DEBUG: Drag finished with result: {result}")
|
||||||
|
|
||||||
|
|
||||||
|
def add_dynamic_logic_item(self, block_item):
|
||||||
|
"""
|
||||||
|
Triggered when a 'begin' block is dropped on the canvas.
|
||||||
|
Adds a corresponding 'logic' block to this library.
|
||||||
|
"""
|
||||||
|
# 1. Check for duplicates
|
||||||
|
# We don't want to add "Joint 1" five times if they drag five 'begin' blocks
|
||||||
|
|
||||||
|
label = block_item.label_text
|
||||||
|
|
||||||
|
items = self.findItems(label, Qt.MatchExactly)
|
||||||
|
for item in items:
|
||||||
|
if item.data(Qt.UserRole) == "logic":
|
||||||
|
print(f"DEBUG: {label} (logic) already exists in library. Skipping.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 2. Add the item as a 'logic' type
|
||||||
|
# In your system, logic blocks have no fields (they are just variables)
|
||||||
|
print(f"DEBUG: Dynamically adding '{label}' as a logic block.")
|
||||||
|
self.add_item(label, "logic", fields=[])
|
||||||
|
|
||||||
|
def update_item_name(self, old_name, new_name):
|
||||||
|
print(f"[DEBUG - Library] Searching for items matching: '{old_name}'")
|
||||||
|
items = self.findItems(old_name, Qt.MatchExactly)
|
||||||
|
|
||||||
|
if not items:
|
||||||
|
print(f"[DEBUG - Library] No items found matching '{old_name}'")
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
# Ensure we only rename the logic-type items
|
||||||
|
if item.data(Qt.UserRole) == "logic":
|
||||||
|
item.setText(new_name)
|
||||||
|
print(f"[DEBUG - Library] Successfully updated sidebar item to '{new_name}'")
|
||||||
|
|
||||||
|
|
||||||
from PySide6.QtWidgets import QGraphicsLineItem, QGraphicsRectItem, QGraphicsSimpleTextItem
|
from PySide6.QtWidgets import QGraphicsLineItem, QGraphicsRectItem, QGraphicsSimpleTextItem
|
||||||
@@ -3456,12 +3507,40 @@ from PySide6.QtGui import QPen, QColor, QBrush
|
|||||||
|
|
||||||
|
|
||||||
class TopologyCanvas(QGraphicsView):
|
class TopologyCanvas(QGraphicsView):
|
||||||
|
|
||||||
|
beginBlockDropped = Signal(object)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.scene = QGraphicsScene()
|
self.scene = QGraphicsScene()
|
||||||
super().__init__(self.scene)
|
super().__init__(self.scene)
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
|
self.block_library_ref = None
|
||||||
self.scene.setSceneRect(0, 0, 2000, 2000)
|
self.scene.setSceneRect(0, 0, 2000, 2000)
|
||||||
|
self.beginBlockDropped.connect(self.on_new_definition_created)
|
||||||
|
|
||||||
|
def on_new_definition_created(self, block_item):
|
||||||
|
# Connect the block's rename signal to our canvas sync method
|
||||||
|
print(f"[DEBUG - Canvas] Connecting signal for new block: {block_item.label_text}")
|
||||||
|
block_item.signals.nameChanged.connect(self.sync_logic_blocks)
|
||||||
|
|
||||||
|
def sync_logic_blocks(self, old_name, new_name):
|
||||||
|
print(f"[DEBUG - Canvas] Syncing. Old: {old_name}, New: {new_name}")
|
||||||
|
|
||||||
|
# 1. Update existing blocks on canvas (This is already working!)
|
||||||
|
for item in self.scene.items():
|
||||||
|
if isinstance(item, PuzzleBlock) and item.b_type == "logic":
|
||||||
|
if item.label_text == old_name:
|
||||||
|
item.label_text = new_name
|
||||||
|
if hasattr(item, 'label_item'):
|
||||||
|
item.label_item.setText(new_name)
|
||||||
|
item.update()
|
||||||
|
|
||||||
|
# 2. Update Sidebar using the direct reference
|
||||||
|
if self.block_library_ref:
|
||||||
|
print("[DEBUG - Canvas] Found block_library_ref. Calling update...")
|
||||||
|
self.block_library_ref.update_item_name(old_name, new_name)
|
||||||
|
else:
|
||||||
|
print("[DEBUG - Canvas] ERROR: block_library_ref is None. Ensure it is linked in main.py.")
|
||||||
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
@@ -3546,6 +3625,9 @@ class TopologyCanvas(QGraphicsView):
|
|||||||
if not self.perform_snap(new_block, self.mapToScene(event.position().toPoint())):
|
if not self.perform_snap(new_block, self.mapToScene(event.position().toPoint())):
|
||||||
new_block.setPos(self.mapToScene(event.position().toPoint()))
|
new_block.setPos(self.mapToScene(event.position().toPoint()))
|
||||||
|
|
||||||
|
if block_type == "begin":
|
||||||
|
self.beginBlockDropped.emit(new_block)
|
||||||
|
|
||||||
event.acceptProposedAction()
|
event.acceptProposedAction()
|
||||||
|
|
||||||
|
|
||||||
@@ -3958,6 +4040,10 @@ class ModelParameterConfigurationTab(QWidget):
|
|||||||
sidebar_layout = QVBoxLayout(sidebar_container)
|
sidebar_layout = QVBoxLayout(sidebar_container)
|
||||||
|
|
||||||
self.block_library = BlockLibrary(parent_tab=self, stringy=self.mode)
|
self.block_library = BlockLibrary(parent_tab=self, stringy=self.mode)
|
||||||
|
|
||||||
|
self.canvas.block_library_ref = self.block_library
|
||||||
|
|
||||||
|
self.canvas.beginBlockDropped.connect(self.block_library.add_dynamic_logic_item)
|
||||||
|
|
||||||
# Reuse your existing Inspector logic
|
# Reuse your existing Inspector logic
|
||||||
self.inspector_scroll = QScrollArea()
|
self.inspector_scroll = QScrollArea()
|
||||||
|
|||||||
Reference in New Issue
Block a user