Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/obj setting #181

Merged
merged 29 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fdfe7ca
text edit
PingHsunTsai Jun 19, 2024
b415602
text edit name
PingHsunTsai Jun 19, 2024
7330586
change log
PingHsunTsai Jun 20, 2024
6b6a279
add frame attribute
tomvanmele Jun 18, 2024
9c7528b
ruff
tomvanmele Jun 25, 2024
51d455f
coclor dialog
PingHsunTsai Jun 26, 2024
c1f417b
Merge branch 'main' into fix/obj_setting
PingHsunTsai Jun 26, 2024
9900fae
work with config
PingHsunTsai Jun 26, 2024
7891831
clean up
PingHsunTsai Jun 26, 2024
5b5f5e0
rm observer from change log
PingHsunTsai Jun 26, 2024
3479ef3
hide option
PingHsunTsai Jun 26, 2024
e6cea12
fix
PingHsunTsai Jun 27, 2024
8e06a7d
Merge branch 'main' into fix/obj_setting
PingHsunTsai Jul 8, 2024
8737689
add scroll area
PingHsunTsai Jul 9, 2024
43c34a9
value change
PingHsunTsai Jul 10, 2024
6ffd087
Merge branch 'main' into fix/obj_setting
PingHsunTsai Jul 10, 2024
adb280c
clean up
PingHsunTsai Jul 10, 2024
fb1c9c9
clean up camera config
PingHsunTsai Jul 10, 2024
e58586e
slider text edit
PingHsunTsai Jul 11, 2024
9c067e2
rm fix height
PingHsunTsai Jul 12, 2024
40cd133
clean up
PingHsunTsai Jul 12, 2024
8b0b611
update camera setting
PingHsunTsai Jul 12, 2024
2f55065
clean up
PingHsunTsai Jul 12, 2024
a107cc5
clean up default layout
PingHsunTsai Jul 12, 2024
3c9e300
clean
PingHsunTsai Jul 12, 2024
49778fb
textedit fix policy and defaultlayout __new__
PingHsunTsai Jul 12, 2024
8cf9b70
Merge branch 'main' into fix/obj_setting
PingHsunTsai Jul 12, 2024
d9369e2
add show_objshow_objectsetting and show_sceneform setter
PingHsunTsai Jul 12, 2024
19925df
Merge branch 'main' into fix/obj_setting
Licini Jul 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* Added `list` to accepted types for `Scene.add`.
* Added `list[float]` to accepted types for `Camera.position` and `Camera.target`.
* Added `TextEdit` to handle `name` change.
* Added `DefaultLayout` to handle gerneral `layout` setting to minimal.
* Added `ColorDialog` to manage color dialog.
* Added `SettingLayout` to manage complex layout with config input.


### Changed

* Fixed `opacity` bug with `BufferObject`.
* Updated callback to `SceneTree`.
* Updated `ObjectSetting` and `CameraSetting` to support setting from config.
* Updated `Slider` to be able change value with `TextEdit`

### Removed

Expand Down
3 changes: 2 additions & 1 deletion src/compas_viewer/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ def change_view(viewer: "Viewer", mode: Literal["Perspective", "Top", "Front", "


def camera_settings(viewer: "Viewer"):
CameraSettingsDialog().exec()
items = viewer.config.camera.dialog_settings
CameraSettingsDialog(items=items).exec()


camera_settings_cmd = Command(title="Camera Settings", callback=camera_settings)
Expand Down
47 changes: 16 additions & 31 deletions src/compas_viewer/components/camerasetting.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from PySide6.QtWidgets import QVBoxLayout

from compas_viewer.base import Base
from compas_viewer.components.layout import base_layout
from compas_viewer.components.layout import SettingLayout


class CameraSettingsDialog(QDialog, Base):
Expand All @@ -12,6 +12,11 @@ class CameraSettingsDialog(QDialog, Base):
This dialog allows users to modify the camera's target and position and
applies these changes dynamically.

Parameters
----------
items : list
A list of dictionaries containing the settings for the camera.

Attributes
----------
layout : QVBoxLayout
Expand All @@ -30,52 +35,32 @@ class CameraSettingsDialog(QDialog, Base):

Example
-------
>>> dialog = CameraSettingsDialog()
>>> dialog = CameraSettingsDialog(items=items)
>>> dialog.exec()
"""

def __init__(self) -> None:
def __init__(self, items: list[dict]) -> None:
super().__init__()
self.setWindowTitle("Camera Settings")

self.layout = QVBoxLayout(self)
self.camera = self.viewer.renderer.camera
items = [
{
"title": "Camera_Target",
"items": [
{"type": "double_edit", "title": "X", "value": self.camera.target.x, "min_val": None, "max_val": None},
{"type": "double_edit", "title": "Y", "value": self.camera.target.y, "min_val": None, "max_val": None},
{"type": "double_edit", "title": "Z", "value": self.camera.target.z, "min_val": None, "max_val": None},
],
},
{
"title": "Camera_Position",
"items": [
{"type": "double_edit", "title": "X", "value": self.camera.position.x, "min_val": None, "max_val": None},
{"type": "double_edit", "title": "Y", "value": self.camera.position.y, "min_val": None, "max_val": None},
{"type": "double_edit", "title": "Z", "value": self.camera.position.z, "min_val": None, "max_val": None},
],
},
]

camera_setting_layout, self.spin_boxes = base_layout(items)
self.setting_layout = SettingLayout(viewer=self.viewer, items=items, type="camera_setting")

self.layout.addLayout(camera_setting_layout)
self.layout.addLayout(self.setting_layout.layout)

self.update_button = QPushButton("Update Camera", self)
self.update_button.clicked.connect(self.update)
self.layout.addWidget(self.update_button)

def update(self) -> None:
self.viewer.renderer.camera.target.set(
self.spin_boxes["Camera_Target_X"].spinbox.value(),
self.spin_boxes["Camera_Target_Y"].spinbox.value(),
self.spin_boxes["Camera_Target_Z"].spinbox.value(),
self.setting_layout.widgets["Camera_Target_X_double_edit"].spinbox.value(),
self.setting_layout.widgets["Camera_Target_Y_double_edit"].spinbox.value(),
self.setting_layout.widgets["Camera_Target_Z_double_edit"].spinbox.value(),
)
self.viewer.renderer.camera.position.set(
self.spin_boxes["Camera_Position_X"].spinbox.value(),
self.spin_boxes["Camera_Position_Y"].spinbox.value(),
self.spin_boxes["Camera_Position_Z"].spinbox.value(),
self.setting_layout.widgets["Camera_Position_X_double_edit"].spinbox.value(),
self.setting_layout.widgets["Camera_Position_Y_double_edit"].spinbox.value(),
self.setting_layout.widgets["Camera_Position_Z_double_edit"].spinbox.value(),
)
self.accept()
203 changes: 203 additions & 0 deletions src/compas_viewer/components/color.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
from typing import TYPE_CHECKING

from PySide6.QtGui import QColor
from PySide6.QtWidgets import QColorDialog
from PySide6.QtWidgets import QPushButton
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtWidgets import QWidget

from compas.colors import Color
from compas.colors.colordict import ColorDict
from compas_viewer.base import Base
from compas_viewer.components.combobox import ComboBox

if TYPE_CHECKING:
from compas_viewer.scene import ViewerSceneObject


def remap_rgb(value, to_range_one=True):
"""
Remap an RGB value between the range (0, 255) and (0, 1).

Parameters
----------
value : tuple
The RGB value to remap.
to_range_one : bool, optional
If True, remap from (0, 255) to (0, 1). If False, remap from (0, 1) to (0, 255).

Returns
-------
tuple
The remapped RGB value.
"""
factor = 1 / 255 if to_range_one else 255
return tuple(v * factor for v in value)


class ColorComboBox(QWidget, Base):
"""
A custom QWidget for selecting colors from a predefined list and applying the selected color to an object's attribute.

Parameters
----------
obj : ViewerSceneObject, optional
The object to which the selected color will be applied. Defaults to None.
attr : str, optional
The attribute of the object to which the selected color will be applied. Defaults to None.

Attributes
----------
obj : ViewerSceneObject
The object to which the selected color will be applied.
attr : str
The attribute of the object to which the selected color will be applied.
color_options : list of QColor
A list of predefined QColor objects representing available colors.
layout : QVBoxLayout
The layout of the widget.
color_selector : ComboBox
A combo box for selecting colors.

Methods
-------
change_color(color: QColor) -> None
Changes the color of the object's attribute to the selected color.

Example
-------
>>> color_combobox = ColorComboBox(obj=some_obj, attr="linecolor")
>>> color_combobox.show()
"""

def __init__(
self,
obj: "ViewerSceneObject" = None,
attr: str = None,
):
super().__init__()
self.obj = obj
self.attr = attr

self.color_options = [
QColor(255, 255, 255), # White
QColor(211, 211, 211), # LightGray
QColor(190, 190, 190), # Gray
QColor(0, 0, 0), # Black
QColor(255, 0, 0), # Red
QColor(0, 255, 0), # Green
QColor(0, 0, 255), # Blue
QColor(255, 255, 0), # Yellow
QColor(0, 255, 255), # Cyan
QColor(255, 0, 255), # Magenta
]

default_color = getattr(self.obj, self.attr)

if isinstance(default_color, Color):
default_color = default_color.rgb
elif isinstance(default_color, ColorDict):
default_color = default_color.default
else:
raise ValueError("Invalid color type.")
default_color = QColor(*remap_rgb(default_color, to_range_one=False))

self.layout = QVBoxLayout(self)
self.color_selector = ComboBox(self.color_options, self.change_color, paint=True)
self.color_selector.setAssignedColor(default_color)
self.layout.addWidget(self.color_selector)

def change_color(self, color):
rgb = remap_rgb(color.getRgb())[:-1] # rgba to rgb(0-1)
setattr(self.obj, self.attr, Color(*rgb))
self.obj.update()


class ColorDialog(QWidget):
"""
A custom QWidget that provides a QPushButton to open a QColorDialog for selecting colors.

This class is used to manage and display a color attribute of a ViewerSceneObject.
The button shows the current color and allows the user to change the color via a color dialog.

Parameters
----------
obj : ViewerSceneObject, optional
The object whose color attribute is being managed.
attr : str, optional
The attribute name of the color in the object.

Attributes
----------
obj : ViewerSceneObject
The object whose color attribute is being managed.
attr : str
The attribute name of the color in the object.
color_button : QPushButton
The button that displays the current color and opens the color dialog when clicked.
layout : QVBoxLayout
The layout of the widget, which contains the color button.
current_color : QColor
The currently selected color.

Methods
-------
open_color_dialog()
Opens a QColorDialog for the user to select a new color.
set_button_color(color: QColor)
Sets the button's background and text to the provided color.
change_color(color: QColor)
Changes the color attribute of the object to the provided color and updates the object.

Example
-------
>>> obj = ViewerSceneObject() # Assume this is a valid object with a color attribute
>>> color_button = ColorButton(obj=obj, attr="linecolor")
>>> layout = QVBoxLayout()
>>> layout.addWidget(color_button)
>>> window = QWidget()
>>> window.setLayout(layout)
>>> window.show()
"""

def __init__(
self,
obj: "ViewerSceneObject" = None,
attr: str = None,
):
super().__init__()

self.obj = obj
self.attr = attr

default_color = getattr(self.obj, self.attr)
if isinstance(default_color, Color):
default_color = default_color.rgb
elif isinstance(default_color, ColorDict):
default_color = default_color.default
else:
raise ValueError("Invalid color type.")
default_color = QColor(*remap_rgb(default_color, to_range_one=False))

self.color_button = QPushButton(self)
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.color_button)
self.color_button.clicked.connect(self.open_color_dialog)
self.set_button_color(default_color)

def open_color_dialog(self):
color = QColorDialog.getColor()

if color.isValid():
self.change_color(color)
self.set_button_color(color)

def set_button_color(self, color: QColor):
self.color_button.setStyleSheet(f"background-color: {color.name()};")
self.color_button.setText(color.name())
self.current_color = color

def change_color(self, color):
rgb = remap_rgb(color.getRgb())[:-1] # rgba to rgb(0-1)
setattr(self.obj, self.attr, Color(*rgb))
self.obj.update()
Loading