QML Widget Models

See the Qt Quick Widgets guide for an introduction and usage examples.

Vec2Model

Bases: QObject

Holds a Vec2 and exposes its components as QML properties.

Source code in ncca/ngl/qml/vec2_model.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@QmlElement
class Vec2Model(QObject):
    """Holds a Vec2 and exposes its components as QML properties."""

    valueChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize the model with a zero Vec2.

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._value = Vec2(0.0, 0.0)

    def get_x(self) -> float:
        """Return the x component.

        Returns:
            The current x value.
        """
        return float(self._value.x)

    def set_x(self, value: float) -> None:
        """Set the x component and emit valueChanged.

        Args:
            value: The new x value.
        """
        self._value.x = value
        self.valueChanged.emit()

    def get_y(self) -> float:
        """Return the y component.

        Returns:
            The current y value.
        """
        return float(self._value.y)

    def set_y(self, value: float) -> None:
        """Set the y component and emit valueChanged.

        Args:
            value: The new y value.
        """
        self._value.y = value
        self.valueChanged.emit()

    x = Property(float, get_x, set_x, notify=valueChanged)
    y = Property(float, get_y, set_y, notify=valueChanged)

    @Slot(result=Vec2)
    def get_value(self) -> Vec2:
        """Return the current Vec2 value.

        Returns:
            The current value.
        """
        return self._value

    @Slot(Vec2)
    def set_value(self, value: Vec2) -> None:
        """Replace the current value and emit valueChanged.

        Args:
            value: The new Vec2 value.
        """
        self._value = value
        self.valueChanged.emit()

__init__(parent=None)

Initialize the model with a zero Vec2.

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/vec2_model.py
18
19
20
21
22
23
24
25
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize the model with a zero Vec2.

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._value = Vec2(0.0, 0.0)

get_value()

Return the current Vec2 value.

Returns:
  • Vec2

    The current value.

Source code in ncca/ngl/qml/vec2_model.py
64
65
66
67
68
69
70
71
@Slot(result=Vec2)
def get_value(self) -> Vec2:
    """Return the current Vec2 value.

    Returns:
        The current value.
    """
    return self._value

get_x()

Return the x component.

Returns:
  • float

    The current x value.

Source code in ncca/ngl/qml/vec2_model.py
27
28
29
30
31
32
33
def get_x(self) -> float:
    """Return the x component.

    Returns:
        The current x value.
    """
    return float(self._value.x)

get_y()

Return the y component.

Returns:
  • float

    The current y value.

Source code in ncca/ngl/qml/vec2_model.py
44
45
46
47
48
49
50
def get_y(self) -> float:
    """Return the y component.

    Returns:
        The current y value.
    """
    return float(self._value.y)

set_value(value)

Replace the current value and emit valueChanged.

Parameters:
  • value (Vec2) –

    The new Vec2 value.

Source code in ncca/ngl/qml/vec2_model.py
73
74
75
76
77
78
79
80
81
@Slot(Vec2)
def set_value(self, value: Vec2) -> None:
    """Replace the current value and emit valueChanged.

    Args:
        value: The new Vec2 value.
    """
    self._value = value
    self.valueChanged.emit()

set_x(value)

Set the x component and emit valueChanged.

Parameters:
  • value (float) –

    The new x value.

Source code in ncca/ngl/qml/vec2_model.py
35
36
37
38
39
40
41
42
def set_x(self, value: float) -> None:
    """Set the x component and emit valueChanged.

    Args:
        value: The new x value.
    """
    self._value.x = value
    self.valueChanged.emit()

set_y(value)

Set the y component and emit valueChanged.

Parameters:
  • value (float) –

    The new y value.

Source code in ncca/ngl/qml/vec2_model.py
52
53
54
55
56
57
58
59
def set_y(self, value: float) -> None:
    """Set the y component and emit valueChanged.

    Args:
        value: The new y value.
    """
    self._value.y = value
    self.valueChanged.emit()

Vec3Model

Bases: QObject

Holds a Vec3 and exposes its components as QML properties.

Source code in ncca/ngl/qml/vec3_model.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
@QmlElement
class Vec3Model(QObject):
    """Holds a Vec3 and exposes its components as QML properties."""

    valueChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize the model with a zero Vec3.

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._value = Vec3(0.0, 0.0, 0.0)

    def get_x(self) -> float:
        """Return the x component.

        Returns:
            The current x value.
        """
        return float(self._value.x)

    def set_x(self, value: float) -> None:
        """Set the x component and emit valueChanged.

        Args:
            value: The new x value.
        """
        self._value.x = value
        self.valueChanged.emit()

    def get_y(self) -> float:
        """Return the y component.

        Returns:
            The current y value.
        """
        return float(self._value.y)

    def set_y(self, value: float) -> None:
        """Set the y component and emit valueChanged.

        Args:
            value: The new y value.
        """
        self._value.y = value
        self.valueChanged.emit()

    def get_z(self) -> float:
        """Return the z component.

        Returns:
            The current z value.
        """
        return float(self._value.z)

    def set_z(self, value: float) -> None:
        """Set the z component and emit valueChanged.

        Args:
            value: The new z value.
        """
        self._value.z = value
        self.valueChanged.emit()

    x = Property(float, get_x, set_x, notify=valueChanged)
    y = Property(float, get_y, set_y, notify=valueChanged)
    z = Property(float, get_z, set_z, notify=valueChanged)

    @Slot(result=Vec3)
    def get_value(self) -> Vec3:
        """Return the current Vec3 value.

        Returns:
            The current value.
        """
        return self._value

    @Slot(Vec3)
    def set_value(self, value: Vec3) -> None:
        """Replace the current value and emit valueChanged.

        Args:
            value: The new Vec3 value.
        """
        self._value = value
        self.valueChanged.emit()

__init__(parent=None)

Initialize the model with a zero Vec3.

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/vec3_model.py
18
19
20
21
22
23
24
25
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize the model with a zero Vec3.

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._value = Vec3(0.0, 0.0, 0.0)

get_value()

Return the current Vec3 value.

Returns:
  • Vec3

    The current value.

Source code in ncca/ngl/qml/vec3_model.py
82
83
84
85
86
87
88
89
@Slot(result=Vec3)
def get_value(self) -> Vec3:
    """Return the current Vec3 value.

    Returns:
        The current value.
    """
    return self._value

get_x()

Return the x component.

Returns:
  • float

    The current x value.

Source code in ncca/ngl/qml/vec3_model.py
27
28
29
30
31
32
33
def get_x(self) -> float:
    """Return the x component.

    Returns:
        The current x value.
    """
    return float(self._value.x)

get_y()

Return the y component.

Returns:
  • float

    The current y value.

Source code in ncca/ngl/qml/vec3_model.py
44
45
46
47
48
49
50
def get_y(self) -> float:
    """Return the y component.

    Returns:
        The current y value.
    """
    return float(self._value.y)

get_z()

Return the z component.

Returns:
  • float

    The current z value.

Source code in ncca/ngl/qml/vec3_model.py
61
62
63
64
65
66
67
def get_z(self) -> float:
    """Return the z component.

    Returns:
        The current z value.
    """
    return float(self._value.z)

set_value(value)

Replace the current value and emit valueChanged.

Parameters:
  • value (Vec3) –

    The new Vec3 value.

Source code in ncca/ngl/qml/vec3_model.py
91
92
93
94
95
96
97
98
99
@Slot(Vec3)
def set_value(self, value: Vec3) -> None:
    """Replace the current value and emit valueChanged.

    Args:
        value: The new Vec3 value.
    """
    self._value = value
    self.valueChanged.emit()

set_x(value)

Set the x component and emit valueChanged.

Parameters:
  • value (float) –

    The new x value.

Source code in ncca/ngl/qml/vec3_model.py
35
36
37
38
39
40
41
42
def set_x(self, value: float) -> None:
    """Set the x component and emit valueChanged.

    Args:
        value: The new x value.
    """
    self._value.x = value
    self.valueChanged.emit()

set_y(value)

Set the y component and emit valueChanged.

Parameters:
  • value (float) –

    The new y value.

Source code in ncca/ngl/qml/vec3_model.py
52
53
54
55
56
57
58
59
def set_y(self, value: float) -> None:
    """Set the y component and emit valueChanged.

    Args:
        value: The new y value.
    """
    self._value.y = value
    self.valueChanged.emit()

set_z(value)

Set the z component and emit valueChanged.

Parameters:
  • value (float) –

    The new z value.

Source code in ncca/ngl/qml/vec3_model.py
69
70
71
72
73
74
75
76
def set_z(self, value: float) -> None:
    """Set the z component and emit valueChanged.

    Args:
        value: The new z value.
    """
    self._value.z = value
    self.valueChanged.emit()

Vec4Model

Bases: QObject

Holds a Vec4 and exposes its components as QML properties.

Source code in ncca/ngl/qml/vec4_model.py
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
@QmlElement
class Vec4Model(QObject):
    """Holds a Vec4 and exposes its components as QML properties."""

    valueChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize the model with a zero Vec4.

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._value = Vec4(0.0, 0.0, 0.0, 0.0)

    def get_x(self) -> float:
        """Return the x component.

        Returns:
            The current x value.
        """
        return float(self._value.x)

    def set_x(self, value: float) -> None:
        """Set the x component and emit valueChanged.

        Args:
            value: The new x value.
        """
        self._value.x = value
        self.valueChanged.emit()

    def get_y(self) -> float:
        """Return the y component.

        Returns:
            The current y value.
        """
        return float(self._value.y)

    def set_y(self, value: float) -> None:
        """Set the y component and emit valueChanged.

        Args:
            value: The new y value.
        """
        self._value.y = value
        self.valueChanged.emit()

    def get_z(self) -> float:
        """Return the z component.

        Returns:
            The current z value.
        """
        return float(self._value.z)

    def set_z(self, value: float) -> None:
        """Set the z component and emit valueChanged.

        Args:
            value: The new z value.
        """
        self._value.z = value
        self.valueChanged.emit()

    def get_w(self) -> float:
        """Return the w component.

        Returns:
            The current w value.
        """
        return float(self._value.w)

    def set_w(self, value: float) -> None:
        """Set the w component and emit valueChanged.

        Args:
            value: The new w value.
        """
        self._value.w = value
        self.valueChanged.emit()

    x = Property(float, get_x, set_x, notify=valueChanged)
    y = Property(float, get_y, set_y, notify=valueChanged)
    z = Property(float, get_z, set_z, notify=valueChanged)
    w = Property(float, get_w, set_w, notify=valueChanged)

    @Slot(result=Vec4)
    def get_value(self) -> Vec4:
        """Return the current Vec4 value.

        Returns:
            The current value.
        """
        return self._value

    @Slot(Vec4)
    def set_value(self, value: Vec4) -> None:
        """Replace the current value and emit valueChanged.

        Args:
            value: The new Vec4 value.
        """
        self._value = value
        self.valueChanged.emit()

__init__(parent=None)

Initialize the model with a zero Vec4.

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/vec4_model.py
18
19
20
21
22
23
24
25
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize the model with a zero Vec4.

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._value = Vec4(0.0, 0.0, 0.0, 0.0)

get_value()

Return the current Vec4 value.

Returns:
  • Vec4

    The current value.

Source code in ncca/ngl/qml/vec4_model.py
100
101
102
103
104
105
106
107
@Slot(result=Vec4)
def get_value(self) -> Vec4:
    """Return the current Vec4 value.

    Returns:
        The current value.
    """
    return self._value

get_w()

Return the w component.

Returns:
  • float

    The current w value.

Source code in ncca/ngl/qml/vec4_model.py
78
79
80
81
82
83
84
def get_w(self) -> float:
    """Return the w component.

    Returns:
        The current w value.
    """
    return float(self._value.w)

get_x()

Return the x component.

Returns:
  • float

    The current x value.

Source code in ncca/ngl/qml/vec4_model.py
27
28
29
30
31
32
33
def get_x(self) -> float:
    """Return the x component.

    Returns:
        The current x value.
    """
    return float(self._value.x)

get_y()

Return the y component.

Returns:
  • float

    The current y value.

Source code in ncca/ngl/qml/vec4_model.py
44
45
46
47
48
49
50
def get_y(self) -> float:
    """Return the y component.

    Returns:
        The current y value.
    """
    return float(self._value.y)

get_z()

Return the z component.

Returns:
  • float

    The current z value.

Source code in ncca/ngl/qml/vec4_model.py
61
62
63
64
65
66
67
def get_z(self) -> float:
    """Return the z component.

    Returns:
        The current z value.
    """
    return float(self._value.z)

set_value(value)

Replace the current value and emit valueChanged.

Parameters:
  • value (Vec4) –

    The new Vec4 value.

Source code in ncca/ngl/qml/vec4_model.py
109
110
111
112
113
114
115
116
117
@Slot(Vec4)
def set_value(self, value: Vec4) -> None:
    """Replace the current value and emit valueChanged.

    Args:
        value: The new Vec4 value.
    """
    self._value = value
    self.valueChanged.emit()

set_w(value)

Set the w component and emit valueChanged.

Parameters:
  • value (float) –

    The new w value.

Source code in ncca/ngl/qml/vec4_model.py
86
87
88
89
90
91
92
93
def set_w(self, value: float) -> None:
    """Set the w component and emit valueChanged.

    Args:
        value: The new w value.
    """
    self._value.w = value
    self.valueChanged.emit()

set_x(value)

Set the x component and emit valueChanged.

Parameters:
  • value (float) –

    The new x value.

Source code in ncca/ngl/qml/vec4_model.py
35
36
37
38
39
40
41
42
def set_x(self, value: float) -> None:
    """Set the x component and emit valueChanged.

    Args:
        value: The new x value.
    """
    self._value.x = value
    self.valueChanged.emit()

set_y(value)

Set the y component and emit valueChanged.

Parameters:
  • value (float) –

    The new y value.

Source code in ncca/ngl/qml/vec4_model.py
52
53
54
55
56
57
58
59
def set_y(self, value: float) -> None:
    """Set the y component and emit valueChanged.

    Args:
        value: The new y value.
    """
    self._value.y = value
    self.valueChanged.emit()

set_z(value)

Set the z component and emit valueChanged.

Parameters:
  • value (float) –

    The new z value.

Source code in ncca/ngl/qml/vec4_model.py
69
70
71
72
73
74
75
76
def set_z(self, value: float) -> None:
    """Set the z component and emit valueChanged.

    Args:
        value: The new z value.
    """
    self._value.z = value
    self.valueChanged.emit()

TransformModel

Bases: QObject

Combines position/rotation/scale Vec3Models into a Mat4 transform.

Source code in ncca/ngl/qml/transform_model.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
@QmlElement
class TransformModel(QObject):
    """Combines position/rotation/scale Vec3Models into a Mat4 transform."""

    valueChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize child position/rotation/scale models and compute the matrix.

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._position = Vec3Model(self)
        self._rotation = Vec3Model(self)
        self._scale = Vec3Model(self)
        self._scale.x = 1.0
        self._scale.y = 1.0
        self._scale.z = 1.0
        self._rotation_order_index = 0
        self._matrix = Mat4()
        self._position.valueChanged.connect(self._update_matrix)
        self._rotation.valueChanged.connect(self._update_matrix)
        self._scale.valueChanged.connect(self._update_matrix)
        self._update_matrix()

    def get_position(self) -> Vec3Model:
        """Return the position child model.

        Returns:
            The position Vec3Model.
        """
        return self._position

    def get_rotation(self) -> Vec3Model:
        """Return the rotation child model.

        Returns:
            The rotation Vec3Model.
        """
        return self._rotation

    def get_scale(self) -> Vec3Model:
        """Return the scale child model.

        Returns:
            The scale Vec3Model.
        """
        return self._scale

    position = Property(QObject, get_position, constant=True)
    rotation = Property(QObject, get_rotation, constant=True)
    scale = Property(QObject, get_scale, constant=True)

    def get_rotation_order_index(self) -> int:
        """Return the index into ROTATION_ORDERS currently in use.

        Returns:
            The current rotation order index.
        """
        return self._rotation_order_index

    def set_rotation_order_index(self, index: int) -> None:
        """Set the rotation order by index and recompute the matrix.

        Args:
            index: An index into ROTATION_ORDERS.
        """
        self._rotation_order_index = index
        self._update_matrix()

    rotationOrderIndex = Property(
        int, get_rotation_order_index, set_rotation_order_index, notify=valueChanged
    )

    @Slot(result=list)
    def rotation_orders(self) -> list:
        """Return the ordered list of valid rotation order strings.

        Returns:
            The rotation order names, in combo-box order.
        """
        return list(ROTATION_ORDERS)

    def _update_matrix(self) -> None:
        """Recompute the transform matrix from the current child values."""
        position = self._position.get_value()
        rotation = self._rotation.get_value()
        scale = self._scale.get_value()

        tx = Transform()
        tx.set_order(ROTATION_ORDERS[self._rotation_order_index])
        tx.set_position(position.x, position.y, position.z)
        tx.set_rotation(rotation.x, rotation.y, rotation.z)
        tx.set_scale(scale.x, scale.y, scale.z)
        self._matrix = tx.matrix()
        self.valueChanged.emit()

    @Slot(result=Mat4)
    def get_matrix(self) -> Mat4:
        """Return the current transform matrix.

        Returns:
            The current Mat4.
        """
        return self._matrix

    matrix = Property(Mat4, get_matrix, notify=valueChanged)

    @Slot(result=str)
    def matrix_text(self) -> str:
        """Return the current matrix formatted as a readable multi-line string.

        Returns:
            The matrix formatted with 2 decimal places per cell.
        """
        rows = [
            " ".join(f"{self._matrix[r][c]:6.2f}" for c in range(4)) for r in range(4)
        ]
        return "\n".join(rows)

__init__(parent=None)

Initialize child position/rotation/scale models and compute the matrix.

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/transform_model.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize child position/rotation/scale models and compute the matrix.

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._position = Vec3Model(self)
    self._rotation = Vec3Model(self)
    self._scale = Vec3Model(self)
    self._scale.x = 1.0
    self._scale.y = 1.0
    self._scale.z = 1.0
    self._rotation_order_index = 0
    self._matrix = Mat4()
    self._position.valueChanged.connect(self._update_matrix)
    self._rotation.valueChanged.connect(self._update_matrix)
    self._scale.valueChanged.connect(self._update_matrix)
    self._update_matrix()

get_matrix()

Return the current transform matrix.

Returns:
  • Mat4

    The current Mat4.

Source code in ncca/ngl/qml/transform_model.py
114
115
116
117
118
119
120
121
@Slot(result=Mat4)
def get_matrix(self) -> Mat4:
    """Return the current transform matrix.

    Returns:
        The current Mat4.
    """
    return self._matrix

get_position()

Return the position child model.

Returns:
Source code in ncca/ngl/qml/transform_model.py
42
43
44
45
46
47
48
def get_position(self) -> Vec3Model:
    """Return the position child model.

    Returns:
        The position Vec3Model.
    """
    return self._position

get_rotation()

Return the rotation child model.

Returns:
Source code in ncca/ngl/qml/transform_model.py
50
51
52
53
54
55
56
def get_rotation(self) -> Vec3Model:
    """Return the rotation child model.

    Returns:
        The rotation Vec3Model.
    """
    return self._rotation

get_rotation_order_index()

Return the index into ROTATION_ORDERS currently in use.

Returns:
  • int

    The current rotation order index.

Source code in ncca/ngl/qml/transform_model.py
70
71
72
73
74
75
76
def get_rotation_order_index(self) -> int:
    """Return the index into ROTATION_ORDERS currently in use.

    Returns:
        The current rotation order index.
    """
    return self._rotation_order_index

get_scale()

Return the scale child model.

Returns:
Source code in ncca/ngl/qml/transform_model.py
58
59
60
61
62
63
64
def get_scale(self) -> Vec3Model:
    """Return the scale child model.

    Returns:
        The scale Vec3Model.
    """
    return self._scale

matrix_text()

Return the current matrix formatted as a readable multi-line string.

Returns:
  • str

    The matrix formatted with 2 decimal places per cell.

Source code in ncca/ngl/qml/transform_model.py
125
126
127
128
129
130
131
132
133
134
135
@Slot(result=str)
def matrix_text(self) -> str:
    """Return the current matrix formatted as a readable multi-line string.

    Returns:
        The matrix formatted with 2 decimal places per cell.
    """
    rows = [
        " ".join(f"{self._matrix[r][c]:6.2f}" for c in range(4)) for r in range(4)
    ]
    return "\n".join(rows)

rotation_orders()

Return the ordered list of valid rotation order strings.

Returns:
  • list

    The rotation order names, in combo-box order.

Source code in ncca/ngl/qml/transform_model.py
91
92
93
94
95
96
97
98
@Slot(result=list)
def rotation_orders(self) -> list:
    """Return the ordered list of valid rotation order strings.

    Returns:
        The rotation order names, in combo-box order.
    """
    return list(ROTATION_ORDERS)

set_rotation_order_index(index)

Set the rotation order by index and recompute the matrix.

Parameters:
  • index (int) –

    An index into ROTATION_ORDERS.

Source code in ncca/ngl/qml/transform_model.py
78
79
80
81
82
83
84
85
def set_rotation_order_index(self, index: int) -> None:
    """Set the rotation order by index and recompute the matrix.

    Args:
        index: An index into ROTATION_ORDERS.
    """
    self._rotation_order_index = index
    self._update_matrix()

LookAtModel

Bases: QObject

Combines eye/look Vec3Models and a world-up choice into a view Mat4.

Source code in ncca/ngl/qml/lookat_model.py
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
@QmlElement
class LookAtModel(QObject):
    """Combines eye/look Vec3Models and a world-up choice into a view Mat4."""

    valueChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize eye/look child models and compute the initial view matrix.

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._eye = Vec3Model(self)
        self._eye.x = 2.0
        self._eye.y = 2.0
        self._eye.z = 2.0
        self._look = Vec3Model(self)
        self._up_index = 0
        self._matrix = Mat4()
        self._eye.valueChanged.connect(self._update_matrix)
        self._look.valueChanged.connect(self._update_matrix)
        self._update_matrix()

    def get_eye(self) -> Vec3Model:
        """Return the eye child model.

        Returns:
            The eye Vec3Model.
        """
        return self._eye

    def get_look(self) -> Vec3Model:
        """Return the look-at child model.

        Returns:
            The look Vec3Model.
        """
        return self._look

    eye = Property(QObject, get_eye, constant=True)
    look = Property(QObject, get_look, constant=True)

    def get_up_index(self) -> int:
        """Return the index into WORLD_UP currently in use.

        Returns:
            The current world-up index.
        """
        return self._up_index

    def set_up_index(self, index: int) -> None:
        """Set the world-up vector by index and recompute the matrix.

        Args:
            index: An index into WORLD_UP.
        """
        self._up_index = index
        self._update_matrix()

    upIndex = Property(int, get_up_index, set_up_index, notify=valueChanged)

    @Slot(result=list)
    def up_names(self) -> list:
        """Return the ordered list of world-up display names.

        Returns:
            The world-up names, in combo-box order.
        """
        return list(WORLD_UP_NAMES)

    def _update_matrix(self) -> None:
        """Recompute the view matrix from the current eye/look/up values."""
        eye = self._eye.get_value()
        look = self._look.get_value()
        up = WORLD_UP[self._up_index]
        self._matrix = look_at(eye, look, up)
        self.valueChanged.emit()

    @Slot(result=Mat4)
    def get_matrix(self) -> Mat4:
        """Return the current view matrix.

        Returns:
            The current Mat4.
        """
        return self._matrix

    matrix = Property(Mat4, get_matrix, notify=valueChanged)

    @Slot(result=str)
    def matrix_text(self) -> str:
        """Return the current matrix formatted as a readable multi-line string.

        Returns:
            The matrix formatted with 2 decimal places per cell.
        """
        rows = [
            " ".join(f"{self._matrix[r][c]:6.2f}" for c in range(4)) for r in range(4)
        ]
        return "\n".join(rows)

__init__(parent=None)

Initialize eye/look child models and compute the initial view matrix.

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/lookat_model.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize eye/look child models and compute the initial view matrix.

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._eye = Vec3Model(self)
    self._eye.x = 2.0
    self._eye.y = 2.0
    self._eye.z = 2.0
    self._look = Vec3Model(self)
    self._up_index = 0
    self._matrix = Mat4()
    self._eye.valueChanged.connect(self._update_matrix)
    self._look.valueChanged.connect(self._update_matrix)
    self._update_matrix()

get_eye()

Return the eye child model.

Returns:
Source code in ncca/ngl/qml/lookat_model.py
41
42
43
44
45
46
47
def get_eye(self) -> Vec3Model:
    """Return the eye child model.

    Returns:
        The eye Vec3Model.
    """
    return self._eye

get_look()

Return the look-at child model.

Returns:
Source code in ncca/ngl/qml/lookat_model.py
49
50
51
52
53
54
55
def get_look(self) -> Vec3Model:
    """Return the look-at child model.

    Returns:
        The look Vec3Model.
    """
    return self._look

get_matrix()

Return the current view matrix.

Returns:
  • Mat4

    The current Mat4.

Source code in ncca/ngl/qml/lookat_model.py
 96
 97
 98
 99
100
101
102
103
@Slot(result=Mat4)
def get_matrix(self) -> Mat4:
    """Return the current view matrix.

    Returns:
        The current Mat4.
    """
    return self._matrix

get_up_index()

Return the index into WORLD_UP currently in use.

Returns:
  • int

    The current world-up index.

Source code in ncca/ngl/qml/lookat_model.py
60
61
62
63
64
65
66
def get_up_index(self) -> int:
    """Return the index into WORLD_UP currently in use.

    Returns:
        The current world-up index.
    """
    return self._up_index

matrix_text()

Return the current matrix formatted as a readable multi-line string.

Returns:
  • str

    The matrix formatted with 2 decimal places per cell.

Source code in ncca/ngl/qml/lookat_model.py
107
108
109
110
111
112
113
114
115
116
117
@Slot(result=str)
def matrix_text(self) -> str:
    """Return the current matrix formatted as a readable multi-line string.

    Returns:
        The matrix formatted with 2 decimal places per cell.
    """
    rows = [
        " ".join(f"{self._matrix[r][c]:6.2f}" for c in range(4)) for r in range(4)
    ]
    return "\n".join(rows)

set_up_index(index)

Set the world-up vector by index and recompute the matrix.

Parameters:
  • index (int) –

    An index into WORLD_UP.

Source code in ncca/ngl/qml/lookat_model.py
68
69
70
71
72
73
74
75
def set_up_index(self, index: int) -> None:
    """Set the world-up vector by index and recompute the matrix.

    Args:
        index: An index into WORLD_UP.
    """
    self._up_index = index
    self._update_matrix()

up_names()

Return the ordered list of world-up display names.

Returns:
  • list

    The world-up names, in combo-box order.

Source code in ncca/ngl/qml/lookat_model.py
79
80
81
82
83
84
85
86
@Slot(result=list)
def up_names(self) -> list:
    """Return the ordered list of world-up display names.

    Returns:
        The world-up names, in combo-box order.
    """
    return list(WORLD_UP_NAMES)

PerspectiveModel

Bases: QObject

Combines fov/aspect/near/far and a clip-space mode into a perspective Mat4.

Source code in ncca/ngl/qml/perspective_model.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
@QmlElement
class PerspectiveModel(QObject):
    """Combines fov/aspect/near/far and a clip-space mode into a perspective Mat4."""

    valueChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize the model with default projection parameters.

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._fov = 45.0
        self._aspect = 1.333
        self._near = 0.1
        self._far = 100.0
        self._mode_index = 0
        self._matrix = Mat4()
        self._update_matrix()

    def get_fov(self) -> float:
        """Return the field of view in degrees.

        Returns:
            The current fov value.
        """
        return self._fov

    def set_fov(self, value: float) -> None:
        """Set the field of view and recompute the matrix.

        Args:
            value: The new fov value in degrees.
        """
        self._fov = value
        self._update_matrix()

    fov = Property(float, get_fov, set_fov, notify=valueChanged)

    def get_aspect(self) -> float:
        """Return the aspect ratio.

        Returns:
            The current aspect ratio.
        """
        return self._aspect

    def set_aspect(self, value: float) -> None:
        """Set the aspect ratio and recompute the matrix.

        Args:
            value: The new aspect ratio.
        """
        self._aspect = value
        self._update_matrix()

    aspect = Property(float, get_aspect, set_aspect, notify=valueChanged)

    def get_near(self) -> float:
        """Return the near clipping plane distance.

        Returns:
            The current near value.
        """
        return self._near

    def set_near(self, value: float) -> None:
        """Set the near clipping plane distance and recompute the matrix.

        Args:
            value: The new near value.
        """
        self._near = value
        self._update_matrix()

    near = Property(float, get_near, set_near, notify=valueChanged)

    def get_far(self) -> float:
        """Return the far clipping plane distance.

        Returns:
            The current far value.
        """
        return self._far

    def set_far(self, value: float) -> None:
        """Set the far clipping plane distance and recompute the matrix.

        Args:
            value: The new far value.
        """
        self._far = value
        self._update_matrix()

    far = Property(float, get_far, set_far, notify=valueChanged)

    def get_mode_index(self) -> int:
        """Return the index into MODE_NAMES currently in use.

        Returns:
            The current mode index.
        """
        return self._mode_index

    def set_mode_index(self, index: int) -> None:
        """Set the clip-space mode by index and recompute the matrix.

        Args:
            index: An index into MODE_NAMES/MODES.
        """
        self._mode_index = index
        self._update_matrix()

    modeIndex = Property(int, get_mode_index, set_mode_index, notify=valueChanged)

    @Slot(result=list)
    def mode_names(self) -> list:
        """Return the ordered list of clip-space mode display names.

        Returns:
            The mode names, in combo-box order.
        """
        return list(MODE_NAMES)

    def _update_matrix(self) -> None:
        """Recompute the perspective matrix from the current property values."""
        self._matrix = perspective(
            self._fov, self._aspect, self._near, self._far, MODES[self._mode_index]
        )
        self.valueChanged.emit()

    @Slot(result=Mat4)
    def get_matrix(self) -> Mat4:
        """Return the current perspective matrix.

        Returns:
            The current Mat4.
        """
        return self._matrix

    matrix = Property(Mat4, get_matrix, notify=valueChanged)

    @Slot(result=str)
    def matrix_text(self) -> str:
        """Return the current matrix formatted as a readable multi-line string.

        Returns:
            The matrix formatted with 2 decimal places per cell.
        """
        rows = [
            " ".join(f"{self._matrix[r][c]:6.2f}" for c in range(4)) for r in range(4)
        ]
        return "\n".join(rows)

__init__(parent=None)

Initialize the model with default projection parameters.

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/perspective_model.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize the model with default projection parameters.

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._fov = 45.0
    self._aspect = 1.333
    self._near = 0.1
    self._far = 100.0
    self._mode_index = 0
    self._matrix = Mat4()
    self._update_matrix()

get_aspect()

Return the aspect ratio.

Returns:
  • float

    The current aspect ratio.

Source code in ncca/ngl/qml/perspective_model.py
55
56
57
58
59
60
61
def get_aspect(self) -> float:
    """Return the aspect ratio.

    Returns:
        The current aspect ratio.
    """
    return self._aspect

get_far()

Return the far clipping plane distance.

Returns:
  • float

    The current far value.

Source code in ncca/ngl/qml/perspective_model.py
93
94
95
96
97
98
99
def get_far(self) -> float:
    """Return the far clipping plane distance.

    Returns:
        The current far value.
    """
    return self._far

get_fov()

Return the field of view in degrees.

Returns:
  • float

    The current fov value.

Source code in ncca/ngl/qml/perspective_model.py
36
37
38
39
40
41
42
def get_fov(self) -> float:
    """Return the field of view in degrees.

    Returns:
        The current fov value.
    """
    return self._fov

get_matrix()

Return the current perspective matrix.

Returns:
  • Mat4

    The current Mat4.

Source code in ncca/ngl/qml/perspective_model.py
147
148
149
150
151
152
153
154
@Slot(result=Mat4)
def get_matrix(self) -> Mat4:
    """Return the current perspective matrix.

    Returns:
        The current Mat4.
    """
    return self._matrix

get_mode_index()

Return the index into MODE_NAMES currently in use.

Returns:
  • int

    The current mode index.

Source code in ncca/ngl/qml/perspective_model.py
112
113
114
115
116
117
118
def get_mode_index(self) -> int:
    """Return the index into MODE_NAMES currently in use.

    Returns:
        The current mode index.
    """
    return self._mode_index

get_near()

Return the near clipping plane distance.

Returns:
  • float

    The current near value.

Source code in ncca/ngl/qml/perspective_model.py
74
75
76
77
78
79
80
def get_near(self) -> float:
    """Return the near clipping plane distance.

    Returns:
        The current near value.
    """
    return self._near

matrix_text()

Return the current matrix formatted as a readable multi-line string.

Returns:
  • str

    The matrix formatted with 2 decimal places per cell.

Source code in ncca/ngl/qml/perspective_model.py
158
159
160
161
162
163
164
165
166
167
168
@Slot(result=str)
def matrix_text(self) -> str:
    """Return the current matrix formatted as a readable multi-line string.

    Returns:
        The matrix formatted with 2 decimal places per cell.
    """
    rows = [
        " ".join(f"{self._matrix[r][c]:6.2f}" for c in range(4)) for r in range(4)
    ]
    return "\n".join(rows)

mode_names()

Return the ordered list of clip-space mode display names.

Returns:
  • list

    The mode names, in combo-box order.

Source code in ncca/ngl/qml/perspective_model.py
131
132
133
134
135
136
137
138
@Slot(result=list)
def mode_names(self) -> list:
    """Return the ordered list of clip-space mode display names.

    Returns:
        The mode names, in combo-box order.
    """
    return list(MODE_NAMES)

set_aspect(value)

Set the aspect ratio and recompute the matrix.

Parameters:
  • value (float) –

    The new aspect ratio.

Source code in ncca/ngl/qml/perspective_model.py
63
64
65
66
67
68
69
70
def set_aspect(self, value: float) -> None:
    """Set the aspect ratio and recompute the matrix.

    Args:
        value: The new aspect ratio.
    """
    self._aspect = value
    self._update_matrix()

set_far(value)

Set the far clipping plane distance and recompute the matrix.

Parameters:
  • value (float) –

    The new far value.

Source code in ncca/ngl/qml/perspective_model.py
101
102
103
104
105
106
107
108
def set_far(self, value: float) -> None:
    """Set the far clipping plane distance and recompute the matrix.

    Args:
        value: The new far value.
    """
    self._far = value
    self._update_matrix()

set_fov(value)

Set the field of view and recompute the matrix.

Parameters:
  • value (float) –

    The new fov value in degrees.

Source code in ncca/ngl/qml/perspective_model.py
44
45
46
47
48
49
50
51
def set_fov(self, value: float) -> None:
    """Set the field of view and recompute the matrix.

    Args:
        value: The new fov value in degrees.
    """
    self._fov = value
    self._update_matrix()

set_mode_index(index)

Set the clip-space mode by index and recompute the matrix.

Parameters:
  • index (int) –

    An index into MODE_NAMES/MODES.

Source code in ncca/ngl/qml/perspective_model.py
120
121
122
123
124
125
126
127
def set_mode_index(self, index: int) -> None:
    """Set the clip-space mode by index and recompute the matrix.

    Args:
        index: An index into MODE_NAMES/MODES.
    """
    self._mode_index = index
    self._update_matrix()

set_near(value)

Set the near clipping plane distance and recompute the matrix.

Parameters:
  • value (float) –

    The new near value.

Source code in ncca/ngl/qml/perspective_model.py
82
83
84
85
86
87
88
89
def set_near(self, value: float) -> None:
    """Set the near clipping plane distance and recompute the matrix.

    Args:
        value: The new near value.
    """
    self._near = value
    self._update_matrix()

RGBColourModel

Bases: QObject

Holds an RGB Vec3 colour and exposes r/g/b plus a hex swatch colour.

Source code in ncca/ngl/qml/rgb_colour_model.py
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
@QmlElement
class RGBColourModel(QObject):
    """Holds an RGB Vec3 colour and exposes r/g/b plus a hex swatch colour."""

    colourChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize the model with white (1, 1, 1).

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._colour = Vec3(1.0, 1.0, 1.0)

    def get_r(self) -> float:
        """Return the red channel.

        Returns:
            The current red value.
        """
        return float(self._colour.x)

    def set_r(self, value: float) -> None:
        """Set the red channel and emit colourChanged.

        Args:
            value: The new red value.
        """
        self._colour.x = value
        self.colourChanged.emit()

    def get_g(self) -> float:
        """Return the green channel.

        Returns:
            The current green value.
        """
        return float(self._colour.y)

    def set_g(self, value: float) -> None:
        """Set the green channel and emit colourChanged.

        Args:
            value: The new green value.
        """
        self._colour.y = value
        self.colourChanged.emit()

    def get_b(self) -> float:
        """Return the blue channel.

        Returns:
            The current blue value.
        """
        return float(self._colour.z)

    def set_b(self, value: float) -> None:
        """Set the blue channel and emit colourChanged.

        Args:
            value: The new blue value.
        """
        self._colour.z = value
        self.colourChanged.emit()

    r = Property(float, get_r, set_r, notify=colourChanged)
    g = Property(float, get_g, set_g, notify=colourChanged)
    b = Property(float, get_b, set_b, notify=colourChanged)

    def get_hex(self) -> str:
        """Return the colour as a `#RRGGBB` hex string.

        Returns:
            The hex colour string.
        """
        return QColor.fromRgbF(self._colour.x, self._colour.y, self._colour.z).name()

    hex = Property(str, get_hex, notify=colourChanged)

    @Slot(result=Vec3)
    def get_value(self) -> Vec3:
        """Return the current colour as a Vec3.

        Returns:
            The current colour.
        """
        return self._colour

    @Slot(Vec3)
    def set_value(self, value: Vec3) -> None:
        """Replace the current colour and emit colourChanged.

        Args:
            value: The new colour value.
        """
        self._colour = value
        self.colourChanged.emit()

__init__(parent=None)

Initialize the model with white (1, 1, 1).

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/rgb_colour_model.py
19
20
21
22
23
24
25
26
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize the model with white (1, 1, 1).

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._colour = Vec3(1.0, 1.0, 1.0)

get_b()

Return the blue channel.

Returns:
  • float

    The current blue value.

Source code in ncca/ngl/qml/rgb_colour_model.py
62
63
64
65
66
67
68
def get_b(self) -> float:
    """Return the blue channel.

    Returns:
        The current blue value.
    """
    return float(self._colour.z)

get_g()

Return the green channel.

Returns:
  • float

    The current green value.

Source code in ncca/ngl/qml/rgb_colour_model.py
45
46
47
48
49
50
51
def get_g(self) -> float:
    """Return the green channel.

    Returns:
        The current green value.
    """
    return float(self._colour.y)

get_hex()

Return the colour as a #RRGGBB hex string.

Returns:
  • str

    The hex colour string.

Source code in ncca/ngl/qml/rgb_colour_model.py
83
84
85
86
87
88
89
def get_hex(self) -> str:
    """Return the colour as a `#RRGGBB` hex string.

    Returns:
        The hex colour string.
    """
    return QColor.fromRgbF(self._colour.x, self._colour.y, self._colour.z).name()

get_r()

Return the red channel.

Returns:
  • float

    The current red value.

Source code in ncca/ngl/qml/rgb_colour_model.py
28
29
30
31
32
33
34
def get_r(self) -> float:
    """Return the red channel.

    Returns:
        The current red value.
    """
    return float(self._colour.x)

get_value()

Return the current colour as a Vec3.

Returns:
  • Vec3

    The current colour.

Source code in ncca/ngl/qml/rgb_colour_model.py
 93
 94
 95
 96
 97
 98
 99
100
@Slot(result=Vec3)
def get_value(self) -> Vec3:
    """Return the current colour as a Vec3.

    Returns:
        The current colour.
    """
    return self._colour

set_b(value)

Set the blue channel and emit colourChanged.

Parameters:
  • value (float) –

    The new blue value.

Source code in ncca/ngl/qml/rgb_colour_model.py
70
71
72
73
74
75
76
77
def set_b(self, value: float) -> None:
    """Set the blue channel and emit colourChanged.

    Args:
        value: The new blue value.
    """
    self._colour.z = value
    self.colourChanged.emit()

set_g(value)

Set the green channel and emit colourChanged.

Parameters:
  • value (float) –

    The new green value.

Source code in ncca/ngl/qml/rgb_colour_model.py
53
54
55
56
57
58
59
60
def set_g(self, value: float) -> None:
    """Set the green channel and emit colourChanged.

    Args:
        value: The new green value.
    """
    self._colour.y = value
    self.colourChanged.emit()

set_r(value)

Set the red channel and emit colourChanged.

Parameters:
  • value (float) –

    The new red value.

Source code in ncca/ngl/qml/rgb_colour_model.py
36
37
38
39
40
41
42
43
def set_r(self, value: float) -> None:
    """Set the red channel and emit colourChanged.

    Args:
        value: The new red value.
    """
    self._colour.x = value
    self.colourChanged.emit()

set_value(value)

Replace the current colour and emit colourChanged.

Parameters:
  • value (Vec3) –

    The new colour value.

Source code in ncca/ngl/qml/rgb_colour_model.py
102
103
104
105
106
107
108
109
110
@Slot(Vec3)
def set_value(self, value: Vec3) -> None:
    """Replace the current colour and emit colourChanged.

    Args:
        value: The new colour value.
    """
    self._colour = value
    self.colourChanged.emit()

RGBAColourModel

Bases: QObject

Holds an RGBA Vec4 colour and exposes r/g/b/a plus a hex swatch colour.

Source code in ncca/ngl/qml/rgba_colour_model.py
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
@QmlElement
class RGBAColourModel(QObject):
    """Holds an RGBA Vec4 colour and exposes r/g/b/a plus a hex swatch colour."""

    colourChanged = Signal()

    def __init__(self, parent: QObject | None = None) -> None:
        """Initialize the model with opaque white (1, 1, 1, 1).

        Args:
            parent: The parent QObject.
        """
        super().__init__(parent)
        self._colour = Vec4(1.0, 1.0, 1.0, 1.0)

    def get_r(self) -> float:
        """Return the red channel.

        Returns:
            The current red value.
        """
        return float(self._colour.x)

    def set_r(self, value: float) -> None:
        """Set the red channel and emit colourChanged.

        Args:
            value: The new red value.
        """
        self._colour.x = value
        self.colourChanged.emit()

    def get_g(self) -> float:
        """Return the green channel.

        Returns:
            The current green value.
        """
        return float(self._colour.y)

    def set_g(self, value: float) -> None:
        """Set the green channel and emit colourChanged.

        Args:
            value: The new green value.
        """
        self._colour.y = value
        self.colourChanged.emit()

    def get_b(self) -> float:
        """Return the blue channel.

        Returns:
            The current blue value.
        """
        return float(self._colour.z)

    def set_b(self, value: float) -> None:
        """Set the blue channel and emit colourChanged.

        Args:
            value: The new blue value.
        """
        self._colour.z = value
        self.colourChanged.emit()

    def get_a(self) -> float:
        """Return the alpha channel.

        Returns:
            The current alpha value.
        """
        return float(self._colour.w)

    def set_a(self, value: float) -> None:
        """Set the alpha channel and emit colourChanged.

        Args:
            value: The new alpha value.
        """
        self._colour.w = value
        self.colourChanged.emit()

    r = Property(float, get_r, set_r, notify=colourChanged)
    g = Property(float, get_g, set_g, notify=colourChanged)
    b = Property(float, get_b, set_b, notify=colourChanged)
    a = Property(float, get_a, set_a, notify=colourChanged)

    def get_hex(self) -> str:
        """Return the colour as a `#AARRGGBB` hex string.

        Returns:
            The hex colour string, including alpha.
        """
        colour = QColor.fromRgbF(
            self._colour.x, self._colour.y, self._colour.z, self._colour.w
        )
        return colour.name(QColor.NameFormat.HexArgb)

    hex = Property(str, get_hex, notify=colourChanged)

    @Slot(result=Vec4)
    def get_value(self) -> Vec4:
        """Return the current colour as a Vec4.

        Returns:
            The current colour.
        """
        return self._colour

    @Slot(Vec4)
    def set_value(self, value: Vec4) -> None:
        """Replace the current colour and emit colourChanged.

        Args:
            value: The new colour value.
        """
        self._colour = value
        self.colourChanged.emit()

__init__(parent=None)

Initialize the model with opaque white (1, 1, 1, 1).

Parameters:
  • parent (QObject | None, default: None ) –

    The parent QObject.

Source code in ncca/ngl/qml/rgba_colour_model.py
19
20
21
22
23
24
25
26
def __init__(self, parent: QObject | None = None) -> None:
    """Initialize the model with opaque white (1, 1, 1, 1).

    Args:
        parent: The parent QObject.
    """
    super().__init__(parent)
    self._colour = Vec4(1.0, 1.0, 1.0, 1.0)

get_a()

Return the alpha channel.

Returns:
  • float

    The current alpha value.

Source code in ncca/ngl/qml/rgba_colour_model.py
79
80
81
82
83
84
85
def get_a(self) -> float:
    """Return the alpha channel.

    Returns:
        The current alpha value.
    """
    return float(self._colour.w)

get_b()

Return the blue channel.

Returns:
  • float

    The current blue value.

Source code in ncca/ngl/qml/rgba_colour_model.py
62
63
64
65
66
67
68
def get_b(self) -> float:
    """Return the blue channel.

    Returns:
        The current blue value.
    """
    return float(self._colour.z)

get_g()

Return the green channel.

Returns:
  • float

    The current green value.

Source code in ncca/ngl/qml/rgba_colour_model.py
45
46
47
48
49
50
51
def get_g(self) -> float:
    """Return the green channel.

    Returns:
        The current green value.
    """
    return float(self._colour.y)

get_hex()

Return the colour as a #AARRGGBB hex string.

Returns:
  • str

    The hex colour string, including alpha.

Source code in ncca/ngl/qml/rgba_colour_model.py
101
102
103
104
105
106
107
108
109
110
def get_hex(self) -> str:
    """Return the colour as a `#AARRGGBB` hex string.

    Returns:
        The hex colour string, including alpha.
    """
    colour = QColor.fromRgbF(
        self._colour.x, self._colour.y, self._colour.z, self._colour.w
    )
    return colour.name(QColor.NameFormat.HexArgb)

get_r()

Return the red channel.

Returns:
  • float

    The current red value.

Source code in ncca/ngl/qml/rgba_colour_model.py
28
29
30
31
32
33
34
def get_r(self) -> float:
    """Return the red channel.

    Returns:
        The current red value.
    """
    return float(self._colour.x)

get_value()

Return the current colour as a Vec4.

Returns:
  • Vec4

    The current colour.

Source code in ncca/ngl/qml/rgba_colour_model.py
114
115
116
117
118
119
120
121
@Slot(result=Vec4)
def get_value(self) -> Vec4:
    """Return the current colour as a Vec4.

    Returns:
        The current colour.
    """
    return self._colour

set_a(value)

Set the alpha channel and emit colourChanged.

Parameters:
  • value (float) –

    The new alpha value.

Source code in ncca/ngl/qml/rgba_colour_model.py
87
88
89
90
91
92
93
94
def set_a(self, value: float) -> None:
    """Set the alpha channel and emit colourChanged.

    Args:
        value: The new alpha value.
    """
    self._colour.w = value
    self.colourChanged.emit()

set_b(value)

Set the blue channel and emit colourChanged.

Parameters:
  • value (float) –

    The new blue value.

Source code in ncca/ngl/qml/rgba_colour_model.py
70
71
72
73
74
75
76
77
def set_b(self, value: float) -> None:
    """Set the blue channel and emit colourChanged.

    Args:
        value: The new blue value.
    """
    self._colour.z = value
    self.colourChanged.emit()

set_g(value)

Set the green channel and emit colourChanged.

Parameters:
  • value (float) –

    The new green value.

Source code in ncca/ngl/qml/rgba_colour_model.py
53
54
55
56
57
58
59
60
def set_g(self, value: float) -> None:
    """Set the green channel and emit colourChanged.

    Args:
        value: The new green value.
    """
    self._colour.y = value
    self.colourChanged.emit()

set_r(value)

Set the red channel and emit colourChanged.

Parameters:
  • value (float) –

    The new red value.

Source code in ncca/ngl/qml/rgba_colour_model.py
36
37
38
39
40
41
42
43
def set_r(self, value: float) -> None:
    """Set the red channel and emit colourChanged.

    Args:
        value: The new red value.
    """
    self._colour.x = value
    self.colourChanged.emit()

set_value(value)

Replace the current colour and emit colourChanged.

Parameters:
  • value (Vec4) –

    The new colour value.

Source code in ncca/ngl/qml/rgba_colour_model.py
123
124
125
126
127
128
129
130
131
@Slot(Vec4)
def set_value(self, value: Vec4) -> None:
    """Replace the current colour and emit colourChanged.

    Args:
        value: The new colour value.
    """
    self._colour = value
    self.colourChanged.emit()

Mat2Model

Bases: MatGridModel

Grid model for a Mat2. No rotate/scale method combo (mirrors Mat2Widget).

Source code in ncca/ngl/qml/mat2_model.py
13
14
15
16
17
18
@QmlElement
class Mat2Model(MatGridModel):
    """Grid model for a Mat2. No rotate/scale method combo (mirrors Mat2Widget)."""

    mat_cls = Mat2
    size = 2

Mat3Model

Bases: MatGridModel

Grid model for a Mat3, with a rotate/scale method combo.

Source code in ncca/ngl/qml/mat3_model.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@QmlElement
class Mat3Model(MatGridModel):
    """Grid model for a Mat3, with a rotate/scale method combo."""

    mat_cls = Mat3
    size = 3

    @Slot(result=list)
    def method_names(self) -> list:
        """Return the ordered list of available method names for the combo box.

        Returns:
            The method display names, in combo-box order.
        """
        return list(_METHODS)

    @Slot(str, result=str)
    def method_kind(self, name: str) -> str:
        """Return the parameter kind for a method name.

        Args:
            name: One of the names returned by `method_names()`.

        Returns:
            `"angle"` for a single-degrees method, `"xyz"` for a 3-component one.
        """
        return _METHODS[name][0]

    @Slot(str, float)
    def apply_angle_method(self, name: str, degrees: float) -> None:
        """Apply an angle-based method (rotate_x/y/z) by degrees.

        Args:
            name: The method name (must have kind `"angle"`).
            degrees: The rotation angle in degrees.
        """
        _, factory = _METHODS[name]
        self.set_value(factory(degrees))

    @Slot(str, float, float, float)
    def apply_xyz_method(self, name: str, x: float, y: float, z: float) -> None:
        """Apply an xyz-based method (scale) with the given components.

        Args:
            name: The method name (must have kind `"xyz"`).
            x: The x component.
            y: The y component.
            z: The z component.
        """
        _, factory = _METHODS[name]
        self.set_value(factory(x, y, z))

apply_angle_method(name, degrees)

Apply an angle-based method (rotate_x/y/z) by degrees.

Parameters:
  • name (str) –

    The method name (must have kind "angle").

  • degrees (float) –

    The rotation angle in degrees.

Source code in ncca/ngl/qml/mat3_model.py
49
50
51
52
53
54
55
56
57
58
@Slot(str, float)
def apply_angle_method(self, name: str, degrees: float) -> None:
    """Apply an angle-based method (rotate_x/y/z) by degrees.

    Args:
        name: The method name (must have kind `"angle"`).
        degrees: The rotation angle in degrees.
    """
    _, factory = _METHODS[name]
    self.set_value(factory(degrees))

apply_xyz_method(name, x, y, z)

Apply an xyz-based method (scale) with the given components.

Parameters:
  • name (str) –

    The method name (must have kind "xyz").

  • x (float) –

    The x component.

  • y (float) –

    The y component.

  • z (float) –

    The z component.

Source code in ncca/ngl/qml/mat3_model.py
60
61
62
63
64
65
66
67
68
69
70
71
@Slot(str, float, float, float)
def apply_xyz_method(self, name: str, x: float, y: float, z: float) -> None:
    """Apply an xyz-based method (scale) with the given components.

    Args:
        name: The method name (must have kind `"xyz"`).
        x: The x component.
        y: The y component.
        z: The z component.
    """
    _, factory = _METHODS[name]
    self.set_value(factory(x, y, z))

method_kind(name)

Return the parameter kind for a method name.

Parameters:
  • name (str) –

    One of the names returned by method_names().

Returns:
  • str

    "angle" for a single-degrees method, "xyz" for a 3-component one.

Source code in ncca/ngl/qml/mat3_model.py
37
38
39
40
41
42
43
44
45
46
47
@Slot(str, result=str)
def method_kind(self, name: str) -> str:
    """Return the parameter kind for a method name.

    Args:
        name: One of the names returned by `method_names()`.

    Returns:
        `"angle"` for a single-degrees method, `"xyz"` for a 3-component one.
    """
    return _METHODS[name][0]

method_names()

Return the ordered list of available method names for the combo box.

Returns:
  • list

    The method display names, in combo-box order.

Source code in ncca/ngl/qml/mat3_model.py
28
29
30
31
32
33
34
35
@Slot(result=list)
def method_names(self) -> list:
    """Return the ordered list of available method names for the combo box.

    Returns:
        The method display names, in combo-box order.
    """
    return list(_METHODS)

Mat4Model

Bases: MatGridModel

Grid model for a Mat4, with a rotate/scale/translate method combo.

Source code in ncca/ngl/qml/mat4_model.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@QmlElement
class Mat4Model(MatGridModel):
    """Grid model for a Mat4, with a rotate/scale/translate method combo."""

    mat_cls = Mat4
    size = 4

    @Slot(result=list)
    def method_names(self) -> list:
        """Return the ordered list of available method names for the combo box.

        Returns:
            The method display names, in combo-box order.
        """
        return list(_METHODS)

    @Slot(str, result=str)
    def method_kind(self, name: str) -> str:
        """Return the parameter kind for a method name.

        Args:
            name: One of the names returned by `method_names()`.

        Returns:
            `"angle"` for a single-degrees method, `"xyz"` for a 3-component one.
        """
        return _METHODS[name][0]

    @Slot(str, float)
    def apply_angle_method(self, name: str, degrees: float) -> None:
        """Apply an angle-based method (rotate_x/y/z) by degrees.

        Args:
            name: The method name (must have kind `"angle"`).
            degrees: The rotation angle in degrees.
        """
        _, factory = _METHODS[name]
        self.set_value(factory(degrees))

    @Slot(str, float, float, float)
    def apply_xyz_method(self, name: str, x: float, y: float, z: float) -> None:
        """Apply an xyz-based method (scale/translate) with the given components.

        Args:
            name: The method name (must have kind `"xyz"`).
            x: The x component.
            y: The y component.
            z: The z component.
        """
        _, factory = _METHODS[name]
        self.set_value(factory(x, y, z))

apply_angle_method(name, degrees)

Apply an angle-based method (rotate_x/y/z) by degrees.

Parameters:
  • name (str) –

    The method name (must have kind "angle").

  • degrees (float) –

    The rotation angle in degrees.

Source code in ncca/ngl/qml/mat4_model.py
50
51
52
53
54
55
56
57
58
59
@Slot(str, float)
def apply_angle_method(self, name: str, degrees: float) -> None:
    """Apply an angle-based method (rotate_x/y/z) by degrees.

    Args:
        name: The method name (must have kind `"angle"`).
        degrees: The rotation angle in degrees.
    """
    _, factory = _METHODS[name]
    self.set_value(factory(degrees))

apply_xyz_method(name, x, y, z)

Apply an xyz-based method (scale/translate) with the given components.

Parameters:
  • name (str) –

    The method name (must have kind "xyz").

  • x (float) –

    The x component.

  • y (float) –

    The y component.

  • z (float) –

    The z component.

Source code in ncca/ngl/qml/mat4_model.py
61
62
63
64
65
66
67
68
69
70
71
72
@Slot(str, float, float, float)
def apply_xyz_method(self, name: str, x: float, y: float, z: float) -> None:
    """Apply an xyz-based method (scale/translate) with the given components.

    Args:
        name: The method name (must have kind `"xyz"`).
        x: The x component.
        y: The y component.
        z: The z component.
    """
    _, factory = _METHODS[name]
    self.set_value(factory(x, y, z))

method_kind(name)

Return the parameter kind for a method name.

Parameters:
  • name (str) –

    One of the names returned by method_names().

Returns:
  • str

    "angle" for a single-degrees method, "xyz" for a 3-component one.

Source code in ncca/ngl/qml/mat4_model.py
38
39
40
41
42
43
44
45
46
47
48
@Slot(str, result=str)
def method_kind(self, name: str) -> str:
    """Return the parameter kind for a method name.

    Args:
        name: One of the names returned by `method_names()`.

    Returns:
        `"angle"` for a single-degrees method, `"xyz"` for a 3-component one.
    """
    return _METHODS[name][0]

method_names()

Return the ordered list of available method names for the combo box.

Returns:
  • list

    The method display names, in combo-box order.

Source code in ncca/ngl/qml/mat4_model.py
29
30
31
32
33
34
35
36
@Slot(result=list)
def method_names(self) -> list:
    """Return the ordered list of available method names for the combo box.

    Returns:
        The method display names, in combo-box order.
    """
    return list(_METHODS)

Import path helpers

ncca.ngl.qml is a file-based QML module, so an engine needs its import path set before import ncca.ngl.qml 1.0 will resolve from your own .qml files.

add_import_path

Register ncca.ngl.qml's import path on a QML engine.

Call this once after constructing the engine so that import ncca.ngl.qml resolves in your own .qml files. Works for both QQmlApplicationEngine and QQuickWidget.engine() (both are QQmlEngine).

Source code in ncca/ngl/qml/__init__.py
60
61
62
63
64
65
66
67
def add_import_path(engine: QQmlEngine) -> None:
    """Register ``ncca.ngl.qml``'s import path on a QML engine.

    Call this once after constructing the engine so that ``import ncca.ngl.qml``
    resolves in your own ``.qml`` files. Works for both ``QQmlApplicationEngine``
    and ``QQuickWidget.engine()`` (both are ``QQmlEngine``).
    """
    engine.addImportPath(str(import_path()))

import_path

Return the directory to add to a QML engine's import path.

ncca.ngl.qml is a file-based QML module whose qmldir declares module ncca.ngl.qml, so import ncca.ngl.qml 1.0 only resolves from an external .qml file if the engine's import path is the directory that contains the ncca/ package (parents[3] of this file: qml -> ngl -> ncca -> containing dir), not the qml/ leaf directory.

This is derived from the module file rather than ncca.__file__ because ncca is a PEP 420 namespace package and so has no __file__.

Source code in ncca/ngl/qml/__init__.py
45
46
47
48
49
50
51
52
53
54
55
56
57
def import_path() -> Path:
    """Return the directory to add to a QML engine's import path.

    ``ncca.ngl.qml`` is a file-based QML module whose ``qmldir`` declares
    ``module ncca.ngl.qml``, so ``import ncca.ngl.qml 1.0`` only resolves from
    an external ``.qml`` file if the engine's import path is the directory that
    *contains* the ``ncca/`` package (``parents[3]`` of this file:
    ``qml -> ngl -> ncca -> containing dir``), not the ``qml/`` leaf directory.

    This is derived from the module file rather than ``ncca.__file__`` because
    ``ncca`` is a PEP 420 namespace package and so has no ``__file__``.
    """
    return Path(__file__).parents[3]