Skip to content

Commit

Permalink
Merge pull request #127 from JonasLukasczyk/id_fixes
Browse files Browse the repository at this point in the history
Id fixes
  • Loading branch information
dhrogers authored Aug 13, 2024
2 parents 0cc1715 + bdc6afc commit 17c96e9
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 80 deletions.
132 changes: 132 additions & 0 deletions pycinema/filters/RenderView.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from pycinema import Filter

import numpy
import logging as log

try:
from PySide6 import QtGui, QtCore, QtWidgets
except ImportError:
pass

try:
class _QGraphicsPixmapItem(QtWidgets.QGraphicsPixmapItem):
def __init__(self):
super().__init__()

self.setShapeMode(QtWidgets.QGraphicsPixmapItem.BoundingRectShape)
self.setTransformationMode(QtCore.Qt.SmoothTransformation)

def update(self,rgba):
qimage = QtGui.QImage(
rgba,
rgba.shape[1], rgba.shape[0],
rgba.shape[1] * 4,
QtGui.QImage.Format_RGBA8888
)
self.setPixmap( QtGui.QPixmap(qimage) )

def paint(self, painter, option, widget=None):
super().paint(painter, option, widget)

class _ImageViewer(QtWidgets.QGraphicsView):

def __init__(self,filter):
super().__init__()

self.filter = filter

self.mode = 0
self.mouse_pos_0 = None
self.camera_0 = None

self.setRenderHints(QtGui.QPainter.Antialiasing)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setScene(filter.scene)

def fitInView(self):
rect = QtCore.QRectF(self.scene().itemsBoundingRect())
if rect.isNull():
return
self.resetTransform()
super().fitInView(rect, QtCore.Qt.KeepAspectRatio)

def resizeEvent(self, event):
super().resizeEvent(event)
self.fitInView()

def wheelEvent(self, event):
return

def keyPressEvent(self,event):
if event.key()==32:
self.fitInView()

def mousePressEvent(self,event):
self.mode = 1
self.mouse_pos_0 = event.pos()
self.camera_0 = self.filter.inputs.camera.get()
super().mousePressEvent(event)

def mouseMoveEvent(self,event):
if self.mode != 1: return

delta = event.pos() - self.mouse_pos_0
factor = 0.1
camera_1 = [
# round(sorted([0, 360, self.camera_0[0] + delta.x()*factor])[1], 2),
round((self.camera_0[0] + delta.x()*factor), 2),
round(sorted([-90, 90, self.camera_0[1] + delta.y()*factor])[1], 2),
]
self.filter.inputs.camera.set(camera_1,True,True)

super().mouseMoveEvent(event)

def mouseReleaseEvent(self,event):
if self.mode != 1: return

self.mode = 0
super().mouseReleaseEvent(event)

except NameError:
pass

class RenderView(Filter):

def __init__(self):
self.scene = QtWidgets.QGraphicsScene()

self.canvas = _QGraphicsPixmapItem()
self.scene.addItem(self.canvas)

self.widgets = []

Filter.__init__(
self,
inputs={
'images': [],
'camera': [0,0]
},
outputs={
'images': []
}
)

def generateWidgets(self):
widget = _ImageViewer(self)
self.widgets.append(widget)
return widget

def _update(self):
images = self.inputs.images.get()
if len(images)<1 or 'rgba' not in images[0].channels:
print('[WARNING:RenderView] No input image or missing rgba channel')
self.canvas.update(numpy.zeros((1,1,4)))
return 1

self.canvas.update(images[0].channels['rgba'])

for w in self.widgets:
w.fitInView()

return 1
18 changes: 9 additions & 9 deletions pycinema/filters/Shader.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ def releaseTextures(self):
try:
Shader.ctx = moderngl.create_standalone_context(require=330)
Shader.quad = Shader.ctx.buffer(
numpy.array([
1.0, 1.0,
-1.0, 1.0,
-1.0, -1.0,
1.0, -1.0,
1.0, 1.0
]).astype('f4').tobytes()
)
numpy.array([
1.0, 1.0,
-1.0, 1.0,
-1.0, -1.0,
1.0, -1.0,
1.0, 1.0
]).astype('f4').tobytes()
)
except:
log.warn("Unable to setup OpenGL context.")
log.warning("Unable to setup OpenGL context.")
51 changes: 33 additions & 18 deletions pycinema/filters/TableView.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ def __init__(self):
self.selection_model.setModel(self.proxyModel)
self.selection_model.selectionChanged.connect(self._onSelectionChanged)

self.update_from_selection = False
self.suppress_selection_update = False

self.outputTable = list()

self.widgets = []
self.table_input_time = -1

Filter.__init__(
self,
inputs={
Expand All @@ -85,12 +87,12 @@ def generateWidgets(self):
widget.setSortingEnabled(True)
widget.setSelectionModel(self.selection_model)
widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.widgets.append(widget)
return widget

def _onSelectionChanged(self, selected, deselected):
if self.suppress_selection_update:
return
self.update_from_selection = True
indices = set(self.proxyModel.mapToSource(index).row() for index in self.selection_model.selectedIndexes())

table = self.inputs.table.get()
Expand All @@ -108,32 +110,45 @@ def _update(self):
table = self.inputs.table.get()
input_is_image_list = len(table)>0 and isinstance(table[0],Image)

if not self.update_from_selection:
table_data = table
if input_is_image_list:
table_data = ImagesToTable.imagesToTable(table)
self.model.setData(table_data)
self.update_from_selection = False
if self.table_input_time != self.inputs.table.getTime():
self.table_input_time = self.inputs.table.getTime()
table_data = table
if input_is_image_list:
table_data = ImagesToTable.imagesToTable(table)
self.model.setData(table_data)

selection = self.inputs.selection.get()
selection_indices = None
output_table = None
selection_indices = []
output_table = [[]]
if input_is_image_list:
selection_indices = [i for i in range(0,len(table)) if table[0].meta['id'] in selection]
output_table = [table[i] for i in selection_indices]
else:
id_column_idx = table[0].index('id')
selection_indices = [i for i in range(0,len(table)) if table[i][id_column_idx] in selection]
output_table = [table[0]]
for i in selection_indices:
output_table.append(table[i])
try: id_column_idx = table[0].index('id')
except ValueError: id_column_idx = -1

selection_mode = QtWidgets.QAbstractItemView.ExtendedSelection
if id_column_idx<0:
selection_mode = QtWidgets.QAbstractItemView.NoSelection

else:
selection_indices = [i for i in range(0,len(table)) if table[i][id_column_idx] in selection]
output_table = [table[0]]
for i in selection_indices:
output_table.append(table[i])
for w in self.widgets:
w.setSelectionMode(selection_mode)

self.outputs.table.set( output_table )

self.suppress_selection_update = True
indices_ = [self.model.index(r-1, 0) for r in selection_indices]
mode = QtCore.QItemSelectionModel.Select | QtCore.QItemSelectionModel.Rows
[self.selection_model.select(self.proxyModel.mapFromSource(i), mode) for i in indices_]
if id_column_idx<0:
self.selection_model.clear()
self.inputs.selection.set([])
else:
indices_ = [self.model.index(r-1, 0) for r in selection_indices]
mode = QtCore.QItemSelectionModel.Select | QtCore.QItemSelectionModel.Rows
[self.selection_model.select(self.proxyModel.mapFromSource(i), mode) for i in indices_]
self.suppress_selection_update = False

return 1
1 change: 1 addition & 0 deletions pycinema/filters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .PlotLineItem import *
from .Python import *
from .GetColumn import *
from .RenderView import *
from .ShaderDemoScene import *
from .ShaderFXAA import *
from .ShaderIBS import *
Expand Down
1 change: 1 addition & 0 deletions pycinema/theater/Icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def update_theme():
Icons.icon_save = '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path style="fill:'+icon_color+'" d="M840-680v480q0 33-23.5 56.5T760-120H200q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h480l160 160Zm-80 34L646-760H200v560h560v-446ZM480-240q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM240-560h360v-160H240v160Zm-40-86v446-560 114Z"/></svg>'
Icons.icon_slider = '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path style="fill:'+icon_color+'" d="M200-360q-50 0-85-35t-35-85q0-50 35-85t85-35h560q50 0 85 35t35 85q0 50-35 85t-85 35H200Zm360-80h200q17 0 28.5-11.5T800-480q0-17-11.5-28.5T760-520H560v80Z"/></svg>'
Icons.icon_list = '<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path style="fill:'+icon_color+'" d="M280-600v-80h560v80H280Zm0 160v-80h560v80H280Zm0 160v-80h560v80H280ZM160-600q-17 0-28.5-11.5T120-640q0-17 11.5-28.5T160-680q17 0 28.5 11.5T200-640q0 17-11.5 28.5T160-600Zm0 160q-17 0-28.5-11.5T120-480q0-17 11.5-28.5T160-520q17 0 28.5 11.5T200-480q0 17-11.5 28.5T160-440Zm0 160q-17 0-28.5-11.5T120-320q0-17 11.5-28.5T160-360q17 0 28.5 11.5T200-320q0 17-11.5 28.5T160-280Z"/></svg>'
Icons.icon_directory = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path style="fill:'+icon_color+'" d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h240l80 80h320q33 0 56.5 23.5T880-640v400q0 33-23.5 56.5T800-160H160Z"/></svg>'

def toQIcon(svg_str):
svg_bytes = bytearray(svg_str, encoding='utf-8')
Expand Down
12 changes: 8 additions & 4 deletions pycinema/theater/Theater.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class _Theater(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()

self.setIconSize(QtCore.QSize(512,512))

# init theme
Icons.update_theme();
NodeEditorStyle.update_theme();
Expand Down Expand Up @@ -98,13 +100,15 @@ def saveScript(self):
for _,filter in pycinema.Filter._filters.items():
script += filter.id + ' = pycinema.filters.' + filter.__class__.__name__+'()\n'

getPortType = lambda p: 'inputs' if p.is_input else 'outputs'

script += '\n# properties\n'
for _,filter in pycinema.Filter._filters.items():
for iPortName, iPort in filter.inputs.ports():
if iPort.valueIsPort():
script += filter.id + '.inputs.'+iPortName+ '.set(' + iPort._value.parent.id +'.outputs.'+ iPort._value.name +', False)\n'
script += filter.id + '.inputs.'+iPortName+ '.set(' + iPort._value.parent.id +'.'+getPortType(iPort._value)+'.'+ iPort._value.name +', False)\n'
elif iPort.valueIsPortList():
script += filter.id + '.inputs.'+iPortName+ '.set([' + ','.join([p.parent.id +'.outputs.'+p.name for p in iPort._value]) +'], False)\n'
script += filter.id + '.inputs.'+iPortName+ '.set([' + ','.join([p.parent.id +'.'+getPortType(p._value)+'.'+p.name for p in iPort._value]) +'], False)\n'
else:
v = iPort.get()
if iPort.type == int or iPort.type == float:
Expand Down Expand Up @@ -225,7 +229,7 @@ def __init__(self, args=[]):
Theater.instance.resize(1024, 900)
Theater.instance.show()

scriptkey = None
scriptkey = None
if len(args)>0 and isinstance(args[0], str):
if args[0].endswith('.py'):
Theater.instance.loadScript(args[0], scriptkey, args[1:])
Expand All @@ -234,7 +238,7 @@ def __init__(self, args=[]):
script = pycinema.getPathForScript('browse')
Theater.instance.loadScript(script, scriptkey, [args[0]])

else:
else:
script = pycinema.getPathForScript(args[0])
if script:
print("loading script: " + script)
Expand Down
37 changes: 22 additions & 15 deletions pycinema/theater/node_editor/Edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,20 @@ class Edge(QtWidgets.QGraphicsPathItem):

def __init__(self,port0,port1,parent=None):
super().__init__(parent)
self.port0 = port0
self.port1 = port1

self.setZValue(NES.Z_EDGE_LAYER)


image_port_names = ['image','images']
is_image = port0.port.name in image_port_names or port1.port.name in image_port_names

if is_image:
# image_port_names = ['image','images']
# is_image = port0.port.name in image_port_names or port1.port.name in image_port_names
if self.port0.port.is_input and self.port1.port.is_input:
self.setPen(QtGui.QPen(NES.COLOR_NORMAL, 2, QtCore.Qt.DashLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
elif port0.port.name=='table' or port1.port.name=='table':
self.setPen(QtGui.QPen(NES.COLOR_NORMAL, 2, QtCore.Qt.DotLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
# elif port0.port.name=='table' or port1.port.name=='table':
# self.setPen(QtGui.QPen(NES.COLOR_NORMAL, 2, QtCore.Qt.DotLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
else:
self.setPen(QtGui.QPen(NES.COLOR_NORMAL, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))

self.port0 = port0
self.port1 = port1

self.port0.parentItem().s_moved.connect(self.update)
self.port1.parentItem().s_moved.connect(self.update)

Expand All @@ -40,11 +37,21 @@ def update(self):
path.moveTo(p0)
dx = abs(x0 - x1)
if x0<x1: dx *= 0.5
path.cubicTo(
x0+dx, y0,
x1-dx, y1,
x1,y1
)

temp = lambda x: 50+min(1,max(0,x/200))*200

if self.port0.port.is_input and self.port1.port.is_input:
path.cubicTo(
x0-temp(dx), y0,
x1-temp(dx), y1,
x1,y1
)
else:
path.cubicTo(
x0+dx, y0,
x1-dx, y1,
x1,y1
)

self.setPath(path)

10 changes: 10 additions & 0 deletions pycinema/theater/node_editor/InputText.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from PySide6 import QtCore, QtWidgets, QtGui

from pycinema.theater.node_editor.NodeEditorStyle import NodeEditorStyle as NES
from pycinema.theater.Icons import Icons
from pycinema import Port

class InputText(QtWidgets.QWidget):
Expand Down Expand Up @@ -37,10 +38,19 @@ def __init__(self, port, width, parent=None):
self.edit.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
self.edit.setStyleSheet('border:0;background:transparent;color:'+NES.COLOR_NORMAL_)
self.edit.setReadOnly(False)

self.edit.editingFinished.connect(lambda: self.setValue(self.edit.text()))
self.layout().addWidget(self.edit,1)
port.on('value_set', self.update_callback)
self.updateWidget()

if port.name in ['file','path']:
def get_path():
path = QtWidgets.QFileDialog.getExistingDirectory(None,"Select Cinema Database")
if path: port.set(path)
select_folder_btn = self.edit.addAction(Icons.toQIcon(Icons.icon_directory), QtWidgets.QLineEdit.TrailingPosition);
select_folder_btn.triggered.connect(get_path)
self.edit.children()[-1].setCursor(QtCore.Qt.PointingHandCursor)
else:
self.edit = QtWidgets.QLineEdit()
self.edit.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
Expand Down
Loading

0 comments on commit 17c96e9

Please sign in to comment.