Este projeto não está recebendo atualizações substanciais e terei tempo limitado para isso no futuro. Com o lançamento mais recente, o projeto tornou-se exatamente o que eu queria que fosse: um editor e estrutura fácil e flexível para explorar casos de uso de scripts visuais baseados em fluxo em Python. Se você tiver dúvidas ou outras ideias, sinta-se à vontade para abrir problemas ou bifurcar o projeto e tentar você mesmo.
Ryven é um editor de nó experimental escrito em Python. Ele implementa uma interface visual baseada em Qt para scripts visuais baseados em fluxo em Python. Ele fornece um sistema poderoso para desenvolver nós que executam qualquer código Python e um editor para construir gráficos usando esses nós. Ryven apresenta várias opções de configuração e um modo headless para executar gráficos sem qualquer GUI. Alguns repositórios relevantes do GitHub:
A biblioteca ryvencore-qt
adiciona classes GUI baseadas em Qt para ryvencore ( ./ryvencore-qt/
), e o editor Ryven as reúne em um aplicativo de plataforma cruzada completo ( ./ryven-editor/
).
Depois de instalar o Python e o pip, o Ryven estará disponível no PyPI via
pip install ryven
Há também um pacote conda-forge ( conda install -c conda-forge ryven
).
Ryven pode ser iniciado a partir da linha de comando digitando ryven
. Se você instalou o Ryven em um ambiente virtual Python (ou ambiente conda), o ambiente precisa ser ativado primeiro.
O próprio Ryven vem apenas com alguns pequenos nós de exemplo. Você deve usar Ryven para desenvolver nós ou usar um pacote de nós de terceiros para seu caso de uso, se houver. Os nós de exemplo são - de fato - apenas exemplos e não são estáveis de forma alguma, portanto você não deve depender deles.
Quando instalado, o ryven criará um diretório ~/.ryven/
na página inicial do usuário com a seguinte estrutura:
~/.ryven
├── nodes
│ ├── your_nodes_pkg_1
│ ├── nodes.py
│ └── gui.py
│ └── ...
├── saves
│ ├── your_project_1.json
│ └── ...
└── ryven.cfg
O arquivo ryven.cfg
contém configurações globais para Ryven.
Ryven pode ser configurado de quatro maneiras:
ryven --nodes your_nodes_pkg_1 --no-animations
~/.ryven/ryven.cfg
: nodes = your_nodes_pkg_1 no_animations = True
import ryven ryven . run_ryven ( nodes = [ 'your_nodes_pkg_1' ], no_animations = True )
Digite ryven --help
para obter uma lista de opções disponíveis.
Para implantar um projeto Ryven sem cabeça (sem qualquer GUI), use o comando ryven-console
.
> ryven-console /home/leon/.ryven/saves/basics.json
Welcome to the Ryven Console ! Your project has been loaded.
You can access the ryvencore session by typing ` session ` .
For more information, visit https://leon-thomm.github.io/ryvencore/
>>> f = session.flows[0]
>>> ctr_var_result_node = f.nodes[2]
>>> ctr_set_var_node = f.nodes[8]
>>> ctr_var_result_node.val
3738
>>> ctr_set_var_node.update(0)
>>> ctr_var_result_node.val
3739
ryven
na linha de comandoFile -> Import Example Nodes
e selecione <installation_dir>/example_nodes/std/nodes.py
val
para a cena+
result
ctrl + scroll
Um pacote de nós Ryven é simplesmente um pacote Python típico que contém pelo menos um arquivo nodes.py
e chama a API do nó Ryven para expor as definições do nó.
Navegue para ~/.ryven/nodes/
e crie um subdiretório com a seguinte estrutura
~/.ryven/nodes
└── your_nodes_pkg_1
├── __init__.py
├── nodes.py
└── gui.py
com o seguinte conteúdo:
nodes.py
:
from ryven . node_env import *
# your node definitions go here
export_nodes ([
# list your node classes here
])
@ on_gui_load
def load_gui ():
# import gui sources here only
from . import gui
e gui.py
:
from ryven . gui_env import *
from . import nodes
# your node gui definitions go here
Agora você pode começar a definir seus próprios nós. Vamos definir dois nós básicos. Aquele que gera números aleatórios...
from random import random
class RandNode ( Node ):
"""Generates scaled random float values"""
title = 'Rand'
tags = [ 'random' , 'numbers' ]
init_inputs = [ NodeInputType ()]
init_outputs = [ NodeOutputType ()]
def update_event ( self , inp = - 1 ):
self . set_output_val ( 0 ,
Data ( random () * self . input ( 0 ). payload )
)
...e outro que os imprime
class PrintNode ( Node ):
title = 'Print'
init_inputs = [ NodeInputType ()]
def update_event ( self , inp = - 1 ):
print ( self . input ( 0 ))
e expô-los a Ryven
export_nodes ([
RandNode ,
PrintNode ,
])
É isso! Você pode importar seu pacote de nós no Ryven ( File -> Import Nodes
), colocar os nós no gráfico e conectá-los. Adicione um nó val
e conecte-o ao nó Rand
, para alimentar sua entrada com dados. Se você digitar um número no widget do nó val
e pressionar Enter, ele enviará o número para o nó Rand
, que enviará um número aleatório em escala para o nó Print
, que o imprimirá na saída padrão.
Observe que a saída padrão é, por padrão, o console do editor, que você pode acessar na parte inferior da janela do editor (arraste a alça azul para cima para torná-la visível).
Agora você pode incrementar seus nós com alguma GUI. Ryven roda em Qt, usando PySide2 ou PySide6 (por meio da biblioteca qtpy). Você pode configurar a GUI de seus nós em um arquivo separado e adicionar widgets Qt personalizados aos seus nós. Certifique-se de sempre separar claramente a lógica do nó dos componentes da GUI. Um dos recursos centrais do Ryven é executar projetos sem cabeça (no ryvencore) sem quaisquer dependências de GUI. Para que isso funcione, seus arquivos nodes.py
nunca devem depender diretamente do Qt. Em vez disso, você pode anexar uma GUI personalizada aos seus nós a partir dos arquivos da GUI, conforme mostrado abaixo.
Vamos dar-lhes um pouco de cor e adicionar um controle deslizante ao nó Rand
, em gui.py
:
from qtpy . QtWidgets import QSlider
from qtpy . QtCore import Qt
from ryven . gui_env import *
from . import nodes
class RandSliderWidget ( NodeInputWidget , QSlider ):
"""a standard Qt slider widget, which updates the node
input it is attached to, every time the slider value changes"""
def __init__ ( self , params ):
NodeInputWidget . __init__ ( self , params )
QSlider . __init__ ( self )
self . setOrientation ( Qt . Horizontal )
self . setMinimumWidth ( 100 )
self . setMinimum ( 0 )
self . setMaximum ( 100 )
self . setValue ( 50 )
self . valueChanged . connect ( self . value_changed )
def value_changed ( self , val ):
# updates the node input this widget is attached to
self . update_node_input ( Data ( val ))
def get_state ( self ) -> dict :
# return the state of the widget
return { 'value' : self . value ()}
def set_state ( self , state : dict ):
# set the state of the widget
self . setValue ( state [ 'value' ])
@ node_gui ( nodes . RandNode )
class RandNodeGui ( NodeGUI ):
color = '#fcba03'
# register the input widget class
input_widget_classes = { 'slider' : RandSliderWidget }
# attach the slider widget to the first node input
# display it _below_ the input pin
init_input_widgets = {
0 : { 'name' : 'slider' , 'pos' : 'below' }
}
e é isso! Ryven agora registrará RandNodeGui
como “classe GUI” da classe RandNode
, que serve como um contêiner para todos os itens da UI. Você pode adicionar widgets primários ("principais") personalizados aos seus nós, inserir widgets e personalizar ainda mais a aparência dos nós.
O valor fornecido por um widget de entrada (por exemplo, self.update_node_input(val)
acima) será retornado no nó, ao chamar input()
(por exemplo, self.input(0)
no RandNode
), mas somente quando a entrada correspondente não for conectado . Caso contrário, será retornado o valor da saída conectada.
Encontre mais recursos na página wiki do GitHub neste repositório.
A menos que você declare explicitamente o contrário, qualquer contribuição enviada intencionalmente para inclusão no trabalho por você será licenciada conforme acima, sem quaisquer termos ou condições adicionais.
As contribuições são muito apreciadas. Este projeto não existe sem a comunidade de código aberto. Quero agradecer especialmente às pessoas listadas no arquivo CREDITS.md
.