forked from LeenkxTeam/LNXSDK
P2P Export - Nodes - Patch
This commit is contained in:
@ -223,6 +223,9 @@ class LeenkxExporter:
|
||||
cls.export_network = False
|
||||
if wrd.lnx_network == 'Enabled':
|
||||
cls.export_network = True
|
||||
cls.export_torrent = False
|
||||
if wrd.lnx_torrent == 'Enabled':
|
||||
cls.export_torrent = True
|
||||
|
||||
@staticmethod
|
||||
def write_matrix(matrix):
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class AddTorrentNode(LnxLogicTreeNode):
|
||||
"""Add Torrent"""
|
||||
bl_idname = 'LNAddTorrentNode'
|
||||
bl_label = 'Add Torrent'
|
||||
bl_description = 'Add a torrent file from the network'
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(AddTorrentNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'Torrent')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Title')
|
||||
self.add_output('LnxDynamicSocket', 'Files')
|
||||
self.add_output('LnxNodeSocketAction', 'Done')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
AddTorrentNode.on_register()
|
||||
@ -4,19 +4,71 @@ class CreateLeenkxNode(LnxLogicTreeNode):
|
||||
"""Create Leenkx"""
|
||||
bl_idname = 'LNCreateLeenkxNode'
|
||||
bl_label = 'Create Leenkx'
|
||||
bl_description = 'Create Leenkx'
|
||||
bl_description = ('Open a Leenkx peer connection on the given swarm identifier')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[2:]:
|
||||
self.inputs.remove(socket)
|
||||
if (self.property0 == 'datachannel'
|
||||
and self.property2 != 'inherit'):
|
||||
self.add_input('LnxNodeSocketArray', 'ICE Servers')
|
||||
if self.property3 != 'inherit':
|
||||
self.add_input('LnxNodeSocketArray', 'Trackers')
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('wire', 'Wire', 'BitTorrent wire protocol transport (default)'),
|
||||
('datachannel', 'DataChannel', 'WebRTC data channels for browser/krom peers - shows the ICE Servers input')],
|
||||
name='Transport', default='wire', update=update_sockets)
|
||||
|
||||
property1: HaxeBoolProperty('property1',
|
||||
name='Gossip', description='Relay mode - forward messages to all connected peers', default=False)
|
||||
|
||||
property2: HaxeEnumProperty('property2',
|
||||
items=[('inherit', 'Inherit', 'Use the built-in STUN server list; no ICE Servers input'),
|
||||
('add', 'Add', 'Merge the ICE Servers input on top of the built-in STUN servers'),
|
||||
('override', 'Override', 'Replace the ICE server list with the ICE Servers input')],
|
||||
name='ICE Servers', default='inherit', update=update_sockets)
|
||||
|
||||
property3: HaxeEnumProperty('property3',
|
||||
items=[('inherit', 'Inherit', 'Use the project torrent tracker list; no Trackers input'),
|
||||
('add', 'Add', 'Merge the Trackers input on top of the project tracker list'),
|
||||
('override', 'Override', 'Replace the announce tracker list with the Trackers input')],
|
||||
name='Trackers', default='inherit', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxStringSocket', 'Url', default_value="8001")
|
||||
self.add_input('LnxStringSocket', 'Channel', default_value='8001')
|
||||
if (self.property0 == 'datachannel'
|
||||
and self.property2 != 'inherit'):
|
||||
self.add_input('LnxNodeSocketArray', 'ICE Servers')
|
||||
if self.property3 != 'inherit':
|
||||
self.add_input('LnxNodeSocketArray', 'Trackers')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Connection')
|
||||
self.add_output('LnxDynamicSocket', 'ID')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
layout.prop(self, 'property1')
|
||||
if self.property0 == 'datachannel':
|
||||
layout.prop(self, 'property2')
|
||||
layout.prop(self, 'property3')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
|
||||
@ -5,7 +5,7 @@ class CreateTorrentNode(LnxLogicTreeNode):
|
||||
"""Create Torrent"""
|
||||
bl_idname = 'LNCreateTorrentNode'
|
||||
bl_label = 'Create Torrent'
|
||||
bl_description = 'Create a torrent file from the network'
|
||||
bl_description = ('Build a .torrent from content (file, files or folder)')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
@ -13,17 +13,67 @@ class CreateTorrentNode(LnxLogicTreeNode):
|
||||
super(CreateTorrentNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[1:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_data_inputs()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_data_inputs(self):
|
||||
mode_sockets = {
|
||||
'file': ('LnxDynamicSocket', 'File (Bytes)', 'Content of the single file as Bytes'),
|
||||
'files': ('LnxNodeSocketArray', 'Files ({path, data})', 'Array of {path, data} objects'),
|
||||
'folder': ('LnxStringSocket', 'Folder Path', 'Folder read recursively for content (native targets only)'),
|
||||
}
|
||||
socket_type, label, desc = mode_sockets.get(self.property1, mode_sockets['file'])
|
||||
self.add_input(socket_type, label)
|
||||
self.add_input('LnxStringSocket', 'Name')
|
||||
self.add_input('LnxStringSocket', 'Comment')
|
||||
self.add_input('LnxStringSocket', 'Created By')
|
||||
self.add_input('LnxStringSocket', 'Source')
|
||||
self.add_input('LnxNodeSocketArray', 'Trackers')
|
||||
self.add_input('LnxBoolSocket', 'Private')
|
||||
self.add_input('LnxIntSocket', 'Piece Length')
|
||||
self.add_input('LnxNodeSocketArray', 'Web Seeds')
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('1', 'V1', 'BitTorrent v1 - SHA-1 piece list over one packed stream; works with every client'),
|
||||
('2', 'V2', 'BitTorrent v2 (BEP 52) - SHA-256 merkle tree per file, pieces aligned to file boundaries; needs modern peers'),
|
||||
('3', 'Hybrid', 'One .torrent with both v1 and v2 metadata - two infohashes (btih + btmh) over the same info dict')],
|
||||
name='Version', default='1')
|
||||
|
||||
property1: HaxeEnumProperty('property1',
|
||||
items=[('file', 'File', 'Single file: Data is a Bytes payload'),
|
||||
('files', 'Files', 'Multiple files: Data is an array of {path, data}'),
|
||||
('folder', 'Folder', 'Read a folder recursively (native targets only): Data is a folder path string')],
|
||||
name='Data', default='file', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Data')
|
||||
self._add_data_inputs()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent')
|
||||
self.add_output('LnxNodeSocketAction', 'Done')
|
||||
self.add_output('LnxDynamicSocket', 'Meta')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent Bytes')
|
||||
self.add_output('LnxStringSocket', 'InfoHash')
|
||||
self.add_output('LnxStringSocket', 'Magnet')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
layout.prop(self, 'property1')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
CreateTorrentNode.on_register()
|
||||
CreateTorrentNode.on_register()
|
||||
|
||||
61
leenkx/blender/lnx/logicnode/custom/LN_create_tracker.py
Normal file
61
leenkx/blender/lnx/logicnode/custom/LN_create_tracker.py
Normal file
@ -0,0 +1,61 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class CreateTrackerNode(LnxLogicTreeNode):
|
||||
"""Create Tracker"""
|
||||
bl_idname = 'LNCreateTrackerNode'
|
||||
bl_label = 'Create Tracker Server'
|
||||
bl_description = ('Hosts a local tracker')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CreateTrackerNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[1:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_mode_inputs()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_mode_inputs(self):
|
||||
self.add_input('LnxStringSocket', 'Host', default_value='127.0.0.1')
|
||||
self.add_input('LnxIntSocket', 'Port', default_value=6969)
|
||||
if self.property0 == 'wss':
|
||||
self.add_input('LnxStringSocket', 'Cert File')
|
||||
self.add_input('LnxStringSocket', 'Key File')
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('udp', 'UDP', 'UDP tracker (BEP 15, sys targets only)'),
|
||||
('http', 'HTTP', 'HTTP tracker (BEP 3)'),
|
||||
('ws', 'WS', 'Plain WebSocket tracker (local relay, WebTorrent/web peers)'),
|
||||
('wss', 'WSS', 'Secure WebSocket tracker (WebTorrent/web peers)')],
|
||||
name='Type', default='udp', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self._add_mode_inputs()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Tracker')
|
||||
self.add_output('LnxStringSocket', 'URL')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
CreateTrackerNode.on_register()
|
||||
76
leenkx/blender/lnx/logicnode/custom/LN_download_torrent.py
Normal file
76
leenkx/blender/lnx/logicnode/custom/LN_download_torrent.py
Normal file
@ -0,0 +1,76 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class DownloadTorrentNode(LnxLogicTreeNode):
|
||||
"""Download Torrent"""
|
||||
bl_idname = 'LNDownloadTorrentNode'
|
||||
bl_label = 'Download Torrent'
|
||||
bl_description = ('Add a torrent to a Leenkx connection and start downloading')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DownloadTorrentNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[2:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_id_inputs()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_id_inputs(self):
|
||||
mode_sockets = {
|
||||
'magnet': ('LnxStringSocket', 'Magnet URI', 'Magnet URI (magnet:?xt=...)'),
|
||||
'id': ('LnxStringSocket', 'Infohash', '40-char v1 or 64-char v2 infohash hex'),
|
||||
'file': ('LnxDynamicSocket', 'Torrent File (Bytes)', '.torrent file bytes'),
|
||||
}
|
||||
socket_type, label, desc = mode_sockets.get(self.property0, mode_sockets['magnet'])
|
||||
self.add_input(socket_type, label)
|
||||
if self.property1 != 'inherit':
|
||||
self.add_input('LnxNodeSocketArray', 'Trackers')
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('magnet', 'Magnet', 'Magnet URI (magnet:?xt=...)'),
|
||||
('id', 'Infohash', '40-char v1 or 64-char v2 infohash hex'),
|
||||
('file', 'Torrent File', '.torrent file bytes')],
|
||||
name='Input', default='magnet', update=update_sockets)
|
||||
|
||||
property1: HaxeEnumProperty('property1',
|
||||
items=[('inherit', 'Inherit', 'Use the torrent\'s own trackers plus the connection\'s; no Trackers input'),
|
||||
('add', 'Add', 'Merge the Trackers input on top of the torrent\'s own trackers'),
|
||||
('override', 'Override', 'Replace all trackers with the Trackers input (torrent\'s own and connection defaults are dropped)')],
|
||||
name='Trackers', default='inherit', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self._add_id_inputs()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent')
|
||||
self.add_output('LnxStringSocket', 'Name')
|
||||
self.add_output('LnxNodeSocketArray', 'Files')
|
||||
self.add_output('LnxNodeSocketAction', 'Done')
|
||||
self.add_output('LnxStringSocket', 'InfoHash')
|
||||
self.add_output('LnxStringSocket', 'Magnet')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
layout.prop(self, 'property1')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
DownloadTorrentNode.on_register()
|
||||
77
leenkx/blender/lnx/logicnode/custom/LN_get_torrent_file.py
Normal file
77
leenkx/blender/lnx/logicnode/custom/LN_get_torrent_file.py
Normal file
@ -0,0 +1,77 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class GetTorrentFileNode(LnxLogicTreeNode):
|
||||
"""Get Torrent File"""
|
||||
bl_idname = 'LNGetTorrentFileNode'
|
||||
bl_label = 'Get Torrent File'
|
||||
bl_description = ('Find one file inside a torrent and read its '
|
||||
'stored bytes (webtorrent torrent.files.find + '
|
||||
'file.arrayBuffer). Match By selects how the '
|
||||
'Match input is interpreted: index, exact file '
|
||||
'name, exact path, or extension')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GetTorrentFileNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[3:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_match_input()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_match_input(self):
|
||||
match_sockets = {
|
||||
'index': ('LnxIntSocket', 'Index', 'Position in the torrent file list'),
|
||||
'name': ('LnxStringSocket', 'Name', 'Exact file name, e.g. movie.mp4'),
|
||||
'path': ('LnxStringSocket', 'Path', 'Exact path inside the torrent, e.g. docs/readme.txt'),
|
||||
'ext': ('LnxStringSocket', 'Extension', 'File extension like mp4 or .mp4; first matching file wins'),
|
||||
}
|
||||
socket_type, label, desc = match_sockets.get(self.property0, match_sockets['name'])
|
||||
self.add_input(socket_type, label)
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('index', 'Index', 'Position in the torrent file list; Match is an int'),
|
||||
('name', 'Name', 'Exact file name; Match is a string like movie.mp4'),
|
||||
('path', 'Path', 'Exact path inside the torrent; Match is a string like docs/readme.txt'),
|
||||
('ext', 'Extension', 'First file whose name ends with the extension; Match is mp4 or .mp4')],
|
||||
name='Match By', default='name', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Torrent')
|
||||
self._add_match_input()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'File')
|
||||
self.add_output('LnxStringSocket', 'Name')
|
||||
self.add_output('LnxStringSocket', 'Path')
|
||||
self.add_output('LnxFloatSocket', 'Size')
|
||||
self.add_output('LnxStringSocket', 'Type')
|
||||
self.add_output('LnxDynamicSocket', 'Data')
|
||||
self.add_output('LnxBoolSocket', 'Found')
|
||||
self.add_output('LnxFloatSocket', 'Downloaded')
|
||||
self.add_output('LnxFloatSocket', 'Progress')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
GetTorrentFileNode.on_register()
|
||||
@ -5,63 +5,40 @@ class LeenkxCloseConnectionNode(LnxLogicTreeNode):
|
||||
"""Close connection on the network"""
|
||||
bl_idname = 'LNLeenkxCloseConnectionNode'
|
||||
bl_label = 'Close Leenkx Connection'
|
||||
bl_description = ('Tear down a Leenkx connection, or drop a single peer from it')
|
||||
lnx_version = 1
|
||||
lnx_category = 'Leenkx'
|
||||
ind = 2
|
||||
|
||||
@staticmethod
|
||||
def get_enum_id_value(obj, prop_name, value):
|
||||
return obj.bl_rna.properties[prop_name].enum_items[value].identifier
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[2:]:
|
||||
self.inputs.remove(socket)
|
||||
if self.property0 == 'peer':
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
@staticmethod
|
||||
def get_count_in(type_name):
|
||||
return {
|
||||
'client': 0,
|
||||
'peer': 1
|
||||
}.get(type_name, 0)
|
||||
|
||||
def get_enum(self):
|
||||
return self.get('property0', 0)
|
||||
|
||||
def set_enum(self, value):
|
||||
# Checking the selection of each type
|
||||
select_current = self.get_enum_id_value(self, 'property0', value)
|
||||
select_prev = self.property0
|
||||
|
||||
#Check if type changed
|
||||
if select_prev != select_current:
|
||||
|
||||
for i in self.inputs:
|
||||
self.inputs.remove(i)
|
||||
|
||||
# Arguements for type Host
|
||||
if (self.get_count_in(select_current) == 0):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'Url')
|
||||
|
||||
# Arguements for type Client
|
||||
if (self.get_count_in(select_current) == 1):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
|
||||
self['property0'] = value
|
||||
|
||||
|
||||
property0: HaxeEnumProperty(
|
||||
'property1',
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items = [('client', 'Leenkx Client', 'Close the Leenkx Client connection on the network'),
|
||||
('peer', 'Single Peer', 'Close a Peer connection on network')],
|
||||
('peer', 'Single Peer', 'Drop a peer from the connection (forgets its address; it can rejoin on a new handshake)')],
|
||||
name='', default='client',
|
||||
set=set_enum,
|
||||
get=get_enum)
|
||||
update=update_sockets)
|
||||
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'Url')
|
||||
if self.property0 == 'peer':
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
|
||||
|
||||
@ -9,84 +9,26 @@ class LeenkxEventNode(LnxLogicTreeNode):
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
@staticmethod
|
||||
def get_enum_id_value(obj, prop_name, value):
|
||||
return obj.bl_rna.properties[prop_name].enum_items[value].identifier
|
||||
|
||||
@staticmethod
|
||||
def get_count_in(type_name):
|
||||
return {
|
||||
'client': 0,
|
||||
'host': 1,
|
||||
'securehost': 2
|
||||
}.get(type_name, 0)
|
||||
|
||||
def get_enum(self):
|
||||
return self.get('property0', 0)
|
||||
|
||||
def set_enum(self, value):
|
||||
# Checking the selection of each type
|
||||
select_current = self.get_enum_id_value(self, 'property0', value)
|
||||
select_prev = self.property0
|
||||
|
||||
#Check if type changed
|
||||
if select_prev != select_current:
|
||||
|
||||
for i in self.inputs:
|
||||
self.inputs.remove(i)
|
||||
|
||||
# Arguements for type Client
|
||||
if (self.get_count_in(select_current) == 0):
|
||||
self.add_input('LnxStringSocket', 'Url', default_value="8001")
|
||||
|
||||
|
||||
# Arguements for type Host
|
||||
if (self.get_count_in(select_current) == 1):
|
||||
self.add_input('LnxStringSocket', 'Domain', default_value="127.0.0.1")
|
||||
self.add_input('LnxIntSocket', 'Port', default_value=8001)
|
||||
|
||||
|
||||
# Arguements for type Secure Host
|
||||
if (self.get_count_in(select_current) == 2):
|
||||
self.add_input('LnxStringSocket', 'Domain', default_value="127.0.0.1")
|
||||
self.add_input('LnxIntSocket', 'Port', default_value=8001)
|
||||
|
||||
|
||||
self['property0'] = value
|
||||
|
||||
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('client', 'Client', 'Network client Event listener'),
|
||||
('host', 'Host', 'Network host Event listener'),
|
||||
('securehost', 'Secure Host', 'Network secure host Event listener')],
|
||||
name='',
|
||||
default='client',
|
||||
set=set_enum,
|
||||
get=get_enum)
|
||||
|
||||
|
||||
property1: HaxeEnumProperty(
|
||||
'property1',
|
||||
items = [('onopen', 'OnOpen', 'Listens to onOpen event'),
|
||||
('onmessage', 'OnMessage', 'Listens to onMessage event'),
|
||||
('onerror', 'OnError', 'Listens to onError event'),
|
||||
('onclose', 'OnClose', 'Listens to onClose event'),
|
||||
('onseen', 'OnSeen', 'Listens to onClose event'),
|
||||
('onserver', 'OnServer', 'Listens to onClose event'),
|
||||
('onconnections', 'OnConnections', 'Listens to onClose event'),
|
||||
('onping', 'OnPing', 'Listens to onClose event'),
|
||||
('onleft', 'OnLeft', 'Listens to onClose event'),
|
||||
('ontimeout', 'OnTimeout', 'Listens to onClose event'),
|
||||
('onrpc', 'OnRpc', 'Listens to onClose event'),
|
||||
('onrpcresponse', 'OnRpcResponse', 'Listens to onClose event'),
|
||||
('onwireleft', 'OnWireLeft', 'Listens to onClose event'),
|
||||
('onwireseen', 'OnWireSeen', 'Listens to onClose event'),
|
||||
('ontorrent', 'OnTorrent', 'Listens to onClose event'),
|
||||
('ontracker', 'OnTracker', 'Listens to onClose event'),
|
||||
('onannounce', 'OnAnnounce', 'Listens to onClose event')],
|
||||
name='',
|
||||
default='onopen')
|
||||
property1: HaxeEnumProperty('property1',
|
||||
items = [('onopen', 'OnOpen', 'The connection to the server is open'),
|
||||
('onmessage', 'OnMessage', 'A message arrived; ID is the sender peer id, Data the payload'),
|
||||
('onerror', 'OnError', 'A connection error occurred'),
|
||||
('onclose', 'OnClose', 'The connection was closed'),
|
||||
('onseen', 'OnSeen', 'A peer was discovered; ID is the peer id'),
|
||||
('onserver', 'OnServer', 'The signaling server responded'),
|
||||
('onconnections', 'OnConnections', 'The server sent the peer list; Data is the connection list'),
|
||||
('onping', 'OnPing', 'Heartbeat ping roundtrip completed'),
|
||||
('onleft', 'OnLeft', 'A peer left; ID is the peer id'),
|
||||
('ontimeout', 'OnTimeout', 'A handshake timed out'),
|
||||
('onwireleft', 'OnWireLeft', 'A BitTorrent wire peer disconnected; ID is the peer id'),
|
||||
('onwireseen', 'OnWireSeen', 'A BitTorrent wire peer connected; ID is the peer id'),
|
||||
('ontorrent', 'OnTorrent', 'Torrent activity on the connection; Data is the torrent'),
|
||||
('ontorrentadded', 'OnTorrentAdded', 'A torrent registered on the connection; Data is the Torrent handle'),
|
||||
('ontracker', 'OnTracker', 'A tracker event on the connection'),
|
||||
('onannounce', 'OnAnnounce', 'A tracker announce completed'),
|
||||
('ontorrentdone', 'OnTorrentDone', 'A torrent finished downloading; Data is the torrent'),
|
||||
('onload', 'OnLoad', 'The connection was registered; fires once at startup')],
|
||||
name='', default='onopen')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LeenkxEventNode, self).__init__(*args, **kwargs)
|
||||
@ -95,7 +37,7 @@ class LeenkxEventNode(LnxLogicTreeNode):
|
||||
|
||||
def lnx_init(self, context):
|
||||
#self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxStringSocket', 'Url', default_value="ws://127.0.0.1:8001")
|
||||
self.add_input('LnxStringSocket', 'Channel', default_value='8001')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'ID')
|
||||
@ -103,7 +45,6 @@ class LeenkxEventNode(LnxLogicTreeNode):
|
||||
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
layout.prop(self, 'property1')
|
||||
|
||||
def register():
|
||||
|
||||
@ -9,16 +9,15 @@ class LeenkxMessageParserNode(LnxLogicTreeNode):
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('string', 'String', 'Event for a string over the network'),
|
||||
('vector', 'Vector', 'Event for a vector over the network'),
|
||||
('float', 'Float', 'Event for a float over the network'),
|
||||
('integer', 'Integer', 'Event for an integer over the network'),
|
||||
('boolean', 'Boolean', 'Event for a boolean over the network'),
|
||||
('transform', 'Transform', 'Event for a transform over the network'),
|
||||
('rotation', 'Rotation', 'Event for a rotation over the network')],
|
||||
name='', default='string')
|
||||
property0: HaxeEnumProperty('property0', items=[
|
||||
('string', 'String', 'Parse the message as a string'),
|
||||
('vector', 'Vector', 'Parse the message as a vector (Vec4)'),
|
||||
('float', 'Float', 'Parse the message as a float'),
|
||||
('integer', 'Integer', 'Parse the message as an integer'),
|
||||
('boolean', 'Boolean', 'Parse the message as a boolean'),
|
||||
('transform', 'Transform', 'Parse the message as a transform (Mat4)'),
|
||||
('rotation', 'Rotation', 'Parse the message as a rotation (Quat)')
|
||||
], name='', default='string')
|
||||
|
||||
|
||||
def lnx_init(self, context):
|
||||
|
||||
@ -9,77 +9,55 @@ class LeenkxSendMessageNode(LnxLogicTreeNode):
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
@staticmethod
|
||||
def get_enum_id_value(obj, prop_name, value):
|
||||
return obj.bl_rna.properties[prop_name].enum_items[value].identifier
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
send_all = True
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
if socket.name == 'Send All':
|
||||
send_all = socket.default_value_raw
|
||||
for socket in self.inputs[3:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_data_inputs(send_all)
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
@staticmethod
|
||||
def get_count_in(type_name):
|
||||
return {
|
||||
'client': 0,
|
||||
'host': 1,
|
||||
'securehost': 2
|
||||
}.get(type_name, 0)
|
||||
def _add_data_inputs(self, send_all=True):
|
||||
data_sockets = {
|
||||
'string': ('LnxStringSocket', 'String payload to send'),
|
||||
'vector': ('LnxVectorSocket', 'Vector payload to send'),
|
||||
'float': ('LnxFloatSocket', 'Float payload to send'),
|
||||
'integer': ('LnxIntSocket', 'Integer payload to send'),
|
||||
'boolean': ('LnxBoolSocket', 'Boolean payload to send'),
|
||||
'transform': ('LnxDynamicSocket', 'Transform (Mat4) payload to send'),
|
||||
'rotation': ('LnxRotationSocket', 'Rotation (Quat) payload to send'),
|
||||
}
|
||||
socket_type, desc = data_sockets.get(self.property1, data_sockets['string'])
|
||||
self.add_input(socket_type, 'Data')
|
||||
self.add_input('LnxBoolSocket', 'Send All', default_value=send_all)
|
||||
if not send_all:
|
||||
self._add_id_input()
|
||||
|
||||
def get_enum(self):
|
||||
return self.get('property0', 0)
|
||||
def _add_id_input(self):
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
|
||||
def set_enum(self, value):
|
||||
# Checking the selection of each type
|
||||
select_current = self.get_enum_id_value(self, 'property0', value)
|
||||
select_prev = self.property0
|
||||
def on_socket_val_update(self, context, socket):
|
||||
if socket.name == 'Send All':
|
||||
if (len(self.inputs) > 5
|
||||
and self.inputs[5].name == 'ID'):
|
||||
self.inputs.remove(self.inputs[5])
|
||||
if not socket.default_value_raw:
|
||||
self._add_id_input()
|
||||
super().on_socket_val_update(context, socket)
|
||||
|
||||
#Check if type changed
|
||||
if select_prev != select_current:
|
||||
|
||||
for i in self.inputs:
|
||||
self.inputs.remove(i)
|
||||
|
||||
# Arguements for type Client
|
||||
if (self.get_count_in(select_current) == 0):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'API')
|
||||
self.add_input('LnxDynamicSocket', 'Data')
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
self.add_input('LnxBoolSocket', 'Send All')
|
||||
|
||||
# Arguements for type Host
|
||||
if (self.get_count_in(select_current) == 1):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'API')
|
||||
self.add_input('LnxDynamicSocket', 'Data')
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
self.add_input('LnxBoolSocket', 'Send All')
|
||||
|
||||
|
||||
# Arguements for type Secure Host
|
||||
if (self.get_count_in(select_current) == 2):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'API')
|
||||
self.add_input('LnxDynamicSocket', 'Data')
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
self.add_input('LnxBoolSocket', 'Send All')
|
||||
|
||||
|
||||
self['property0'] = value
|
||||
|
||||
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('client', 'Client', 'Network client Event listener'),
|
||||
('host', 'Host', 'Network host Event listener'),
|
||||
('securehost', 'Secure Host', 'Network secure host Event listener')],
|
||||
name='',
|
||||
default='client',
|
||||
set=set_enum,
|
||||
get=get_enum)
|
||||
|
||||
|
||||
property1: HaxeEnumProperty(
|
||||
'property1',
|
||||
property1: HaxeEnumProperty('property1',
|
||||
items = [('string', 'String', 'Send a string over the network to one or all of the clients'),
|
||||
('vector', 'Vector', 'Send a vector over the network to one or all of the clients'),
|
||||
('float', 'Float', 'Send a float over the network to one or all of the clients'),
|
||||
@ -87,8 +65,12 @@ class LeenkxSendMessageNode(LnxLogicTreeNode):
|
||||
('boolean', 'Boolean', 'Send a boolean over the network to one or all of the clients'),
|
||||
('transform', 'Transform', 'Send a transform over the network to one or all of the clients'),
|
||||
('rotation', 'Rotation', 'Send a rotation over the network to one or all of the clients')],
|
||||
name='',
|
||||
default='string')
|
||||
name='', default='string', update=update_sockets)
|
||||
|
||||
property2: HaxeBoolProperty('property2',
|
||||
name='Encrypted',
|
||||
description='Use full encryption protocol (signing, bencode, box encryption). Disable for fast raw message mode',
|
||||
default=False)
|
||||
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -100,17 +82,15 @@ class LeenkxSendMessageNode(LnxLogicTreeNode):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxStringSocket', 'API')
|
||||
self.add_input('LnxDynamicSocket', 'Data')
|
||||
self.add_input('LnxStringSocket', 'ID')
|
||||
self.add_input('LnxBoolSocket', 'Send All')
|
||||
|
||||
self._add_data_inputs()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
|
||||
|
||||
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
layout.prop(self, 'property1')
|
||||
layout.prop(self, 'property2')
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
|
||||
68
leenkx/blender/lnx/logicnode/custom/LN_parse_torrent.py
Normal file
68
leenkx/blender/lnx/logicnode/custom/LN_parse_torrent.py
Normal file
@ -0,0 +1,68 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class ParseTorrentNode(LnxLogicTreeNode):
|
||||
"""Parse Torrent"""
|
||||
bl_idname = 'LNParseTorrentNode'
|
||||
bl_label = 'Parse Torrent'
|
||||
bl_description = ('Parse a torrent id without joining a swarm')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ParseTorrentNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[1:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_id_input()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_id_input(self):
|
||||
mode_sockets = {
|
||||
'magnet': ('LnxStringSocket', 'Magnet URI', 'Magnet URI (magnet:?xt=...)'),
|
||||
'id': ('LnxStringSocket', 'Infohash', '40-char v1 or 64-char v2 infohash hex'),
|
||||
'file': ('LnxDynamicSocket', 'Torrent File (Bytes)', '.torrent file bytes'),
|
||||
}
|
||||
socket_type, label, desc = mode_sockets.get(self.property0, mode_sockets['magnet'])
|
||||
self.add_input(socket_type, label)
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('magnet', 'Magnet', 'Magnet URI (magnet:?xt=...)'),
|
||||
('id', 'Infohash', '40-char v1 or 64-char v2 infohash hex'),
|
||||
('file', 'Torrent File', '.torrent file bytes')],
|
||||
name='Input', default='magnet', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self._add_id_input()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Meta')
|
||||
self.add_output('LnxStringSocket', 'InfoHash')
|
||||
self.add_output('LnxStringSocket', 'Name')
|
||||
self.add_output('LnxNodeSocketArray', 'Trackers')
|
||||
self.add_output('LnxNodeSocketArray', 'Web Seeds')
|
||||
self.add_output('LnxNodeSocketArray', 'Files')
|
||||
self.add_output('LnxFloatSocket', 'Total Size')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent Bytes')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
ParseTorrentNode.on_register()
|
||||
@ -17,12 +17,14 @@ class SeedTorrentNode(LnxLogicTreeNode):
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Opts [Map]')
|
||||
self.add_input('LnxDynamicSocket', 'Torrent')
|
||||
self.add_input('LnxDynamicSocket', 'Data')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent')
|
||||
self.add_output('LnxNodeSocketAction', 'Done')
|
||||
self.add_output('LnxStringSocket', 'InfoHash')
|
||||
self.add_output('LnxStringSocket', 'Magnet')
|
||||
|
||||
|
||||
def register():
|
||||
|
||||
75
leenkx/blender/lnx/logicnode/custom/LN_set_trackers.py
Normal file
75
leenkx/blender/lnx/logicnode/custom/LN_set_trackers.py
Normal file
@ -0,0 +1,75 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class SetTrackersNode(LnxLogicTreeNode):
|
||||
"""Set Trackers"""
|
||||
bl_idname = 'LNSetTrackersNode'
|
||||
bl_label = 'Set Trackers'
|
||||
bl_description = ('Add/Override edit the tracker announce list of a live torrent')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
tracker_props = {
|
||||
'interval': ('LnxIntSocket', 'Interval'),
|
||||
'port': ('LnxIntSocket', 'Port'),
|
||||
'key': ('LnxIntSocket', 'Key'),
|
||||
'numwant': ('LnxIntSocket', 'Num Want'),
|
||||
'trackerId': ('LnxStringSocket', 'Tracker ID'),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SetTrackersNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def update_sockets(self, context):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[1:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_target_inputs()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_target_inputs(self):
|
||||
if self.property0 in ('add', 'override'):
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Torrent')
|
||||
self.add_input('LnxNodeSocketArray', 'Trackers')
|
||||
else:
|
||||
self.add_input('LnxDynamicSocket', 'Tracker')
|
||||
socket_type, label = self.tracker_props.get(
|
||||
self.property0, self.tracker_props['interval'])
|
||||
self.add_input(socket_type, label)
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('add', 'Add', 'Merge the Trackers input on top of the existing announce list'),
|
||||
('override', 'Override', 'Replace the announce list entirely; running tracker connections are restarted'),
|
||||
('interval', 'Interval', 'Announce interval in seconds'),
|
||||
('port', 'Port', 'Listening port reported to the tracker'),
|
||||
('key', 'Key', 'Session key sent with announces'),
|
||||
('numwant', 'Num Want', 'Number of peers requested per announce'),
|
||||
('trackerId', 'Tracker ID', 'Tracker id echoed back by the tracker')],
|
||||
name='Property', default='add', update=update_sockets)
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self._add_target_inputs()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Target')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
SetTrackersNode.on_register()
|
||||
@ -0,0 +1,31 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class TorrentClientInfoNode(LnxLogicTreeNode):
|
||||
"""Torrent Client Info"""
|
||||
bl_idname = 'LNTorrentClientInfoNode'
|
||||
bl_label = 'Connection Torrents'
|
||||
bl_description = ('Aggregate stats for the torrent client attached')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TorrentClientInfoNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxNodeSocketArray', 'Torrents')
|
||||
self.add_output('LnxIntSocket', 'Count')
|
||||
self.add_output('LnxFloatSocket', 'Down Rate')
|
||||
self.add_output('LnxFloatSocket', 'Up Rate')
|
||||
self.add_output('LnxFloatSocket', 'Progress')
|
||||
self.add_output('LnxFloatSocket', 'Ratio')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
TorrentClientInfoNode.on_register()
|
||||
71
leenkx/blender/lnx/logicnode/custom/LN_torrent_control.py
Normal file
71
leenkx/blender/lnx/logicnode/custom/LN_torrent_control.py
Normal file
@ -0,0 +1,71 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class TorrentControlNode(LnxLogicTreeNode):
|
||||
"""Torrent Control"""
|
||||
bl_idname = 'LNTorrentControlNode'
|
||||
bl_label = 'Torrent Control'
|
||||
bl_description = ('Start, stop, remove or prioritize a torrent.')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TorrentControlNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('start', 'Start', 'Start or resume the torrent session'),
|
||||
('stop', 'Stop', 'Pause the torrent (announces stopped to trackers); it stays registered and can be started again'),
|
||||
('remove', 'Remove', 'Destroy the torrent and remove it from the client'),
|
||||
('remove-data', 'Remove + Data', 'Destroy the torrent and delete the stored content bytes'),
|
||||
('select', 'Select', 'Prioritize a piece range: File handle or Start/End bytes, Priority optional (webtorrent torrent.select)'),
|
||||
('deselect', 'Deselect', 'Drop a priority selection, back to normal order'),
|
||||
('critical', 'Critical', 'Top-priority selection for streaming seeks'),
|
||||
('add-peer', 'Add Peer', 'Connect to a peer directly; Address is host:port (sys/Krom targets only)'),
|
||||
('add-web-seed', 'Add Web Seed', 'Register a BEP 19 webseed; Address is an http(s) URL, fills pieces when peers can\'t serve them')],
|
||||
name='Action', default='start',
|
||||
update=lambda self, context: self._rebuild_inputs())
|
||||
|
||||
def _rebuild_inputs(self):
|
||||
if not self.inputs:
|
||||
return
|
||||
links = {}
|
||||
for socket in self.inputs:
|
||||
for link in socket.links:
|
||||
links.setdefault(socket.name, []).append(
|
||||
(link.from_node, link.from_socket))
|
||||
for socket in self.inputs[3:]:
|
||||
self.inputs.remove(socket)
|
||||
self._add_action_inputs()
|
||||
tree = self.id_data
|
||||
for socket in self.inputs:
|
||||
if socket.name in links:
|
||||
for from_node, from_socket in links[socket.name]:
|
||||
tree.links.new(from_socket, socket)
|
||||
|
||||
def _add_action_inputs(self):
|
||||
if self.property0 in ('select', 'deselect', 'critical'):
|
||||
self.add_input('LnxDynamicSocket', 'File')
|
||||
self.add_input('LnxIntSocket', 'Start')
|
||||
self.add_input('LnxIntSocket', 'End')
|
||||
self.add_input('LnxIntSocket', 'Priority')
|
||||
elif self.property0 == 'add-peer':
|
||||
self.add_input('LnxStringSocket', 'Address')
|
||||
elif self.property0 == 'add-web-seed':
|
||||
self.add_input('LnxStringSocket', 'Address')
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Torrent')
|
||||
self._add_action_inputs()
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
TorrentControlNode.on_register()
|
||||
40
leenkx/blender/lnx/logicnode/custom/LN_torrent_event.py
Normal file
40
leenkx/blender/lnx/logicnode/custom/LN_torrent_event.py
Normal file
@ -0,0 +1,40 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class OnTorrentEventNode(LnxLogicTreeNode):
|
||||
"""On Torrent Event"""
|
||||
bl_idname = 'LNOnTorrentEventNode'
|
||||
bl_label = 'On Torrent Event'
|
||||
bl_description = ('Fires when the selected torrent event happens ')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OnTorrentEventNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
property0: HaxeEnumProperty('property0',
|
||||
items=[('ready', 'Ready', 'Metainfo is known; fires immediately if already ready'),
|
||||
('piece', 'Piece', 'A piece finished downloading; Value is the piece index'),
|
||||
('wire', 'Wire', 'A peer connected; Value is the WireProtocol'),
|
||||
('metadata', 'Metadata', 'ut_metadata fetch completed; Value is the MetaInfo'),
|
||||
('done', 'Done', 'All pieces are downloaded'),
|
||||
('error', 'Error', 'Torrent failed; Value is the error string')],
|
||||
name='Event', default='done')
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Torrent')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent')
|
||||
self.add_output('LnxDynamicSocket', 'Value')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
OnTorrentEventNode.on_register()
|
||||
46
leenkx/blender/lnx/logicnode/custom/LN_torrent_info.py
Normal file
46
leenkx/blender/lnx/logicnode/custom/LN_torrent_info.py
Normal file
@ -0,0 +1,46 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class TorrentInfoNode(LnxLogicTreeNode):
|
||||
"""Torrent Info"""
|
||||
bl_idname = 'LNTorrentInfoNode'
|
||||
bl_label = 'Torrent Info'
|
||||
bl_description = ('Read the state of a torrent: infohash, name, peer count, progress, transfer totals, magnet URI')
|
||||
lnx_category = 'Leenkx'
|
||||
lnx_version = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TorrentInfoNode, self).__init__(*args, **kwargs)
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxDynamicSocket', 'Connection')
|
||||
self.add_input('LnxDynamicSocket', 'Torrent')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
self.add_output('LnxStringSocket', 'InfoHash')
|
||||
self.add_output('LnxStringSocket', 'Name')
|
||||
self.add_output('LnxIntSocket', 'Peers')
|
||||
self.add_output('LnxFloatSocket', 'Progress')
|
||||
self.add_output('LnxFloatSocket', 'Downloaded')
|
||||
self.add_output('LnxFloatSocket', 'Uploaded')
|
||||
self.add_output('LnxBoolSocket', 'Done')
|
||||
self.add_output('LnxStringSocket', 'Magnet')
|
||||
self.add_output('LnxNodeSocketArray', 'Files')
|
||||
self.add_output('LnxIntSocket', 'Num Pieces')
|
||||
self.add_output('LnxIntSocket', 'Piece Length')
|
||||
self.add_output('LnxFloatSocket', 'Total Size')
|
||||
self.add_output('LnxStringSocket', 'Comment')
|
||||
self.add_output('LnxStringSocket', 'Created By')
|
||||
self.add_output('LnxIntSocket', 'Version')
|
||||
self.add_output('LnxStringSocket', 'InfoHash2')
|
||||
self.add_output('LnxFloatSocket', 'Down Rate')
|
||||
self.add_output('LnxFloatSocket', 'Up Rate')
|
||||
self.add_output('LnxBoolSocket', 'Stopped')
|
||||
self.add_output('LnxDynamicSocket', 'Torrent')
|
||||
|
||||
|
||||
def register():
|
||||
add_category('Leenkx', icon='ORIENTATION_CURSOR')
|
||||
TorrentInfoNode.on_register()
|
||||
@ -248,6 +248,7 @@ def export_data_impl(fp, sdk_path):
|
||||
export_navigation = bpy.data.worlds['Lnx'].lnx_navigation != 'Disabled'
|
||||
export_ui = bpy.data.worlds['Lnx'].lnx_ui != 'Disabled'
|
||||
export_network = bpy.data.worlds['Lnx'].lnx_network != 'Disabled'
|
||||
export_torrent = bpy.data.worlds['Lnx'].lnx_torrent != 'Disabled'
|
||||
|
||||
assets.reset()
|
||||
mat_state.material_cache.clear()
|
||||
@ -264,6 +265,7 @@ def export_data_impl(fp, sdk_path):
|
||||
navigation_found = False
|
||||
ui_found = False
|
||||
network_found = False
|
||||
torrent_found = False
|
||||
LeenkxExporter.compress_enabled = wrd.lnx_asset_compression
|
||||
LeenkxExporter.optimize_enabled = state.is_publish and wrd.lnx_optimize_data
|
||||
if not os.path.exists(build_dir + '/compiled/Assets'):
|
||||
@ -326,6 +328,8 @@ def export_data_impl(fp, sdk_path):
|
||||
ui_found = True
|
||||
if LeenkxExporter.export_network:
|
||||
network_found = True
|
||||
if LeenkxExporter.export_torrent:
|
||||
torrent_found = True
|
||||
assets.add(asset_path)
|
||||
|
||||
if physics_found is False: # Disable physics if no rigid body is exported
|
||||
@ -340,6 +344,9 @@ def export_data_impl(fp, sdk_path):
|
||||
if network_found == False:
|
||||
export_network = False
|
||||
|
||||
if torrent_found == False:
|
||||
export_torrent = False
|
||||
|
||||
# Ugly workaround: some logic nodes require Zui code even if no UI is used,
|
||||
# for now enable UI export unless explicitly disabled.
|
||||
export_ui = True
|
||||
@ -349,6 +356,9 @@ def export_data_impl(fp, sdk_path):
|
||||
if wrd.lnx_network == 'Enabled':
|
||||
export_network = True
|
||||
|
||||
if wrd.lnx_torrent == 'Enabled':
|
||||
export_torrent = True
|
||||
|
||||
modules = []
|
||||
if wrd.lnx_audio == 'Enabled':
|
||||
modules.append('audio')
|
||||
@ -360,6 +370,8 @@ def export_data_impl(fp, sdk_path):
|
||||
modules.append('ui')
|
||||
if export_network:
|
||||
modules.append('network')
|
||||
if export_torrent:
|
||||
modules.append('torrent')
|
||||
|
||||
defs = lnx.utils.def_strings_to_array(wrd.world_defs)
|
||||
cdefs = lnx.utils.def_strings_to_array(wrd.compo_defs)
|
||||
@ -451,7 +463,7 @@ def export_data_impl(fp, sdk_path):
|
||||
wrd.lnx_project_version = lnx.utils.change_version_project(wrd.lnx_project_version)
|
||||
|
||||
# Write khafile.js
|
||||
write_data.write_khafilejs(state.is_play, export_physics, export_navigation, export_ui, export_network, state.is_publish, LeenkxExporter.import_traits)
|
||||
write_data.write_khafilejs(state.is_play, export_physics, export_navigation, export_ui, export_network, export_torrent, state.is_publish, LeenkxExporter.import_traits)
|
||||
|
||||
# Write Main.hx - depends on write_khafilejs for writing number of assets
|
||||
scene_name = lnx.utils.get_project_scene_name()
|
||||
|
||||
@ -34,6 +34,16 @@ else:
|
||||
lnx_version = '2026.9'
|
||||
lnx_commit = '$Id: 6b2644d47db169cedd95593497cc283207d23a74 $'
|
||||
|
||||
LNX_TORRENT_DEFAULT_TRACKERS = [
|
||||
'wss://ws1.leenkx.com',
|
||||
'wss://video.blender.org/tracker/socket',
|
||||
]
|
||||
|
||||
LNX_TORRENT_DEFAULT_ICE_SERVERS = [
|
||||
'stun:stun.l.google.com:19302',
|
||||
'stun:global.stun.twilio.com:3478',
|
||||
]
|
||||
|
||||
def get_project_html5_copy(self):
|
||||
return self.get('lnx_project_html5_copy', False)
|
||||
|
||||
@ -282,6 +292,17 @@ def init_properties():
|
||||
('Enabled', 'Enabled', 'Enabled'),
|
||||
('Auto', 'Auto', 'Auto')],
|
||||
name="Networking", default='Auto', description="Include Network library", update=assets.invalidate_compiler_cache)
|
||||
bpy.types.World.lnx_torrent = EnumProperty(
|
||||
items=[('Disabled', 'Disabled', 'Disabled'),
|
||||
('Enabled', 'Enabled', 'Enabled')],
|
||||
name="Torrent", default='Disabled', description="Include Torrent (Leenkx) library", update=assets.invalidate_compiler_cache)
|
||||
bpy.types.World.lnx_torrent_download_dir = StringProperty(name="Download Path", description="Directory torrent downloads are written to. Relative paths resolve against the project directory at runtime; absolute paths are used as-is", default="Downloads", subtype='DIR_PATH', update=assets.invalidate_compiler_cache)
|
||||
bpy.types.World.lnx_torrent_trackers = CollectionProperty(name="Torrent Trackers", description="Default torrent tracker announce URLs", type=bpy.types.PropertyGroup)
|
||||
bpy.types.World.lnx_torrent_trackers_index = IntProperty(name="Torrent Tracker Index", default=0)
|
||||
bpy.types.World.lnx_torrent_ice_servers = CollectionProperty(name="ICE Servers", description="Default ICE/STUN servers used for WebRTC peer connections", type=bpy.types.PropertyGroup)
|
||||
bpy.types.World.lnx_torrent_ice_servers_index = IntProperty(name="ICE Server Index", default=0)
|
||||
bpy.types.World.lnx_torrent_peer_timeout = IntProperty(name="Peer Timeout", description="Milliseconds after which an unresponsive peer is dropped", default=5 * 60 * 1000, min=0, update=assets.invalidate_compiler_cache)
|
||||
bpy.types.World.lnx_torrent_heartbeat = IntProperty(name="Heartbeat", description="Milliseconds between heartbeat packets sent to peers", default=30000, min=0, update=assets.invalidate_compiler_cache)
|
||||
bpy.types.World.lnx_audio = EnumProperty(
|
||||
items=[('Disabled', 'Disabled', 'Disabled'),
|
||||
('Enabled', 'Enabled', 'Enabled')],
|
||||
@ -701,13 +722,23 @@ def create_wrd():
|
||||
wrd.use_fake_user = True # Store data world object, add fake user to keep it alive
|
||||
wrd.lnx_version = lnx_version
|
||||
wrd.lnx_commit = lnx_commit
|
||||
seed_torrent_trackers(wrd)
|
||||
|
||||
def seed_torrent_trackers(wrd):
|
||||
if len(wrd.lnx_torrent_trackers) == 0:
|
||||
for url in LNX_TORRENT_DEFAULT_TRACKERS:
|
||||
wrd.lnx_torrent_trackers.add().name = url
|
||||
if len(wrd.lnx_torrent_ice_servers) == 0:
|
||||
for url in LNX_TORRENT_DEFAULT_ICE_SERVERS:
|
||||
wrd.lnx_torrent_ice_servers.add().name = url
|
||||
|
||||
def init_properties_on_load():
|
||||
if 'Lnx' not in bpy.data.worlds:
|
||||
init_properties()
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
seed_torrent_trackers(wrd)
|
||||
# New project?
|
||||
if bpy.data.filepath == '':
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
wrd.lnx_debug_console = lnx.utils.get_debug_console_auto()
|
||||
lnx.utils.fetch_script_names()
|
||||
|
||||
|
||||
@ -1358,11 +1358,150 @@ class LNX_PT_ProjectModulesPanel(bpy.types.Panel):
|
||||
layout.prop(wrd, 'lnx_navigation_engine')
|
||||
layout.prop(wrd, 'lnx_ui')
|
||||
layout.prop(wrd, 'lnx_network')
|
||||
layout.prop(wrd, 'lnx_torrent')
|
||||
|
||||
layout.prop_search(wrd, 'lnx_khafile', bpy.data, 'texts')
|
||||
layout.prop(wrd, 'lnx_project_root')
|
||||
layout.prop(wrd, 'lnx_external_blends_path')
|
||||
|
||||
|
||||
class LNX_UL_TorrentTrackerList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
layout.prop(item, "name", text="", emboss=False, icon='NETWORK_DRIVE')
|
||||
|
||||
class LnxTorrentTrackerListNewItem(bpy.types.Operator):
|
||||
bl_idname = "lnx_torrent_tracker_list.new_item"
|
||||
bl_label = "Add a new tracker"
|
||||
|
||||
def execute(self, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
wrd.lnx_torrent_trackers.add()
|
||||
wrd.lnx_torrent_trackers_index = len(wrd.lnx_torrent_trackers) - 1
|
||||
assets.invalidate_compiler_cache(wrd, context)
|
||||
return{'FINISHED'}
|
||||
|
||||
class LnxTorrentTrackerListDeleteItem(bpy.types.Operator):
|
||||
bl_idname = "lnx_torrent_tracker_list.delete_item"
|
||||
bl_label = "Deletes a tracker"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
return len(wrd.lnx_torrent_trackers) > 0
|
||||
|
||||
def execute(self, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
index = wrd.lnx_torrent_trackers_index
|
||||
|
||||
wrd.lnx_torrent_trackers.remove(index)
|
||||
wrd.lnx_torrent_trackers_index = min(max(0, index - 1), len(wrd.lnx_torrent_trackers) - 1)
|
||||
assets.invalidate_compiler_cache(wrd, context)
|
||||
return{'FINISHED'}
|
||||
|
||||
class LnxTorrentTrackerListReset(bpy.types.Operator):
|
||||
bl_idname = "lnx_torrent_tracker_list.reset_items"
|
||||
bl_label = "Reset To Default Trackers"
|
||||
bl_description = "Remove all trackers and add back the default ones"
|
||||
|
||||
def execute(self, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
wrd.lnx_torrent_trackers.clear()
|
||||
for url in props.LNX_TORRENT_DEFAULT_TRACKERS:
|
||||
wrd.lnx_torrent_trackers.add().name = url
|
||||
wrd.lnx_torrent_trackers_index = 0
|
||||
assets.invalidate_compiler_cache(wrd, context)
|
||||
return{'FINISHED'}
|
||||
|
||||
class LNX_UL_TorrentIceServerList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
layout.prop(item, "name", text="", emboss=False, icon='URL')
|
||||
|
||||
class LnxTorrentIceServerListNewItem(bpy.types.Operator):
|
||||
bl_idname = "lnx_torrent_ice_server_list.new_item"
|
||||
bl_label = "Add a new ICE server"
|
||||
|
||||
def execute(self, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
wrd.lnx_torrent_ice_servers.add()
|
||||
wrd.lnx_torrent_ice_servers_index = len(wrd.lnx_torrent_ice_servers) - 1
|
||||
assets.invalidate_compiler_cache(wrd, context)
|
||||
return{'FINISHED'}
|
||||
|
||||
class LnxTorrentIceServerListDeleteItem(bpy.types.Operator):
|
||||
bl_idname = "lnx_torrent_ice_server_list.delete_item"
|
||||
bl_label = "Deletes an ICE server"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
return len(wrd.lnx_torrent_ice_servers) > 0
|
||||
|
||||
def execute(self, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
index = wrd.lnx_torrent_ice_servers_index
|
||||
|
||||
wrd.lnx_torrent_ice_servers.remove(index)
|
||||
wrd.lnx_torrent_ice_servers_index = min(max(0, index - 1), len(wrd.lnx_torrent_ice_servers) - 1)
|
||||
assets.invalidate_compiler_cache(wrd, context)
|
||||
return{'FINISHED'}
|
||||
|
||||
class LnxTorrentIceServerListReset(bpy.types.Operator):
|
||||
bl_idname = "lnx_torrent_ice_server_list.reset_items"
|
||||
bl_label = "Reset To Default ICE Servers"
|
||||
bl_description = "Remove all ICE servers and add back the default ones"
|
||||
|
||||
def execute(self, context):
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
wrd.lnx_torrent_ice_servers.clear()
|
||||
for url in props.LNX_TORRENT_DEFAULT_ICE_SERVERS:
|
||||
wrd.lnx_torrent_ice_servers.add().name = url
|
||||
wrd.lnx_torrent_ice_servers_index = 0
|
||||
assets.invalidate_compiler_cache(wrd, context)
|
||||
return{'FINISHED'}
|
||||
|
||||
class LNX_PT_LeenkxNetworkPanel(bpy.types.Panel):
|
||||
bl_label = "Leenkx Network"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "render"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
|
||||
col = layout.column()
|
||||
col.enabled = wrd.lnx_torrent != 'Disabled'
|
||||
|
||||
col.prop(wrd, "lnx_torrent_download_dir")
|
||||
col.prop(wrd, "lnx_torrent_peer_timeout")
|
||||
col.prop(wrd, "lnx_torrent_heartbeat")
|
||||
|
||||
col.label(text="Trackers")
|
||||
rows = 2
|
||||
if len(wrd.lnx_torrent_trackers) > 1:
|
||||
rows = 4
|
||||
row = col.row()
|
||||
row.template_list("LNX_UL_TorrentTrackerList", "The_List", wrd, "lnx_torrent_trackers", wrd, "lnx_torrent_trackers_index", rows=rows)
|
||||
btns = row.column(align=True)
|
||||
btns.operator("lnx_torrent_tracker_list.new_item", icon='ADD', text="")
|
||||
btns.operator("lnx_torrent_tracker_list.delete_item", icon='REMOVE', text="")
|
||||
|
||||
col.operator("lnx_torrent_tracker_list.reset_items", icon='FILE_REFRESH')
|
||||
|
||||
col.label(text="ICE Servers")
|
||||
rows = 2
|
||||
if len(wrd.lnx_torrent_ice_servers) > 1:
|
||||
rows = 4
|
||||
row = col.row()
|
||||
row.template_list("LNX_UL_TorrentIceServerList", "The_List", wrd, "lnx_torrent_ice_servers", wrd, "lnx_torrent_ice_servers_index", rows=rows)
|
||||
btns = row.column(align=True)
|
||||
btns.operator("lnx_torrent_ice_server_list.new_item", icon='ADD', text="")
|
||||
btns.operator("lnx_torrent_ice_server_list.delete_item", icon='REMOVE', text="")
|
||||
|
||||
col.operator("lnx_torrent_ice_server_list.reset_items", icon='FILE_REFRESH')
|
||||
|
||||
class LnxVirtualInputPanel(bpy.types.Panel):
|
||||
bl_label = "Leenkx Virtual Input"
|
||||
bl_space_type = "PROPERTIES"
|
||||
@ -3107,6 +3246,15 @@ __REG_CLASSES = (
|
||||
LNX_PT_ProjectFlagsDebugConsolePanel,
|
||||
LNX_PT_ProjectWindowPanel,
|
||||
LNX_PT_ProjectModulesPanel,
|
||||
LNX_UL_TorrentTrackerList,
|
||||
LnxTorrentTrackerListNewItem,
|
||||
LnxTorrentTrackerListDeleteItem,
|
||||
LnxTorrentTrackerListReset,
|
||||
LNX_UL_TorrentIceServerList,
|
||||
LnxTorrentIceServerListNewItem,
|
||||
LnxTorrentIceServerListDeleteItem,
|
||||
LnxTorrentIceServerListReset,
|
||||
LNX_PT_LeenkxNetworkPanel,
|
||||
LNX_PT_RenderPathPanel,
|
||||
LNX_PT_RenderPathRendererPanel,
|
||||
LNX_PT_RenderPathShadowsPanel,
|
||||
|
||||
@ -158,7 +158,7 @@ def remove_readonly(func, path, excinfo):
|
||||
func(path)
|
||||
|
||||
|
||||
def write_khafilejs(is_play, export_physics: bool, export_navigation: bool, export_ui: bool, export_network: bool, is_publish: bool,
|
||||
def write_khafilejs(is_play, export_physics: bool, export_navigation: bool, export_ui: bool, export_network: bool, export_torrent: bool, is_publish: bool,
|
||||
import_traits: List[str]) -> None:
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
rpdat = lnx.utils.get_rp()
|
||||
@ -482,9 +482,16 @@ let project = new Project('""" + lnx.utils.safesrc(wrd.lnx_project_name + '-' +
|
||||
if not os.path.exists('Libraries/network'):
|
||||
khafile.write(add_leenkx_library(sdk_path, 'lib/network', rel_path=do_relpath_sdk))
|
||||
assets.add_khafile_def('lnx_network')
|
||||
lnxjs_path = sdk_path + '/lib/leenkx_tools/lnxjs/Leenkx.js'
|
||||
lnxjs_path = lnxjs_path.replace('\\', '/').replace('//', '/')
|
||||
khafile.write(add_assets(lnxjs_path, rel_path=do_relpath_sdk))
|
||||
#lnxjs_path = sdk_path + '/lib/leenkx_tools/lnxjs/Leenkx.js'
|
||||
#lnxjs_path = lnxjs_path.replace('\\', '/').replace('//', '/')
|
||||
#khafile.write(add_assets(lnxjs_path, rel_path=do_relpath_sdk))
|
||||
|
||||
if export_torrent:
|
||||
assets.add_khafile_def('lnx_torrent')
|
||||
if state.target in ('windows-hl', 'linux-hl', 'macos-hl'):
|
||||
if not os.path.exists('Libraries/datachannel'):
|
||||
khafile.write(add_leenkx_library(sdk_path + '/lib/', 'datachannel', rel_path=do_relpath_sdk))
|
||||
assets.add_khafile_def('lnx_datachannel')
|
||||
|
||||
if not wrd.lnx_minimize:
|
||||
assets.add_khafile_def('lnx_json')
|
||||
@ -736,6 +743,19 @@ class Main {
|
||||
elif wrd.lnx_canvas_img_scaling_quality == 'high':
|
||||
f.write("\n" + content_indent + "leenkx.ui.Canvas.imageScaleQuality = kha.graphics2.ImageScaleQuality.High;")
|
||||
|
||||
if wrd.lnx_torrent != 'Disabled':
|
||||
dl_dir = wrd.lnx_torrent_download_dir
|
||||
if dl_dir.startswith('//'):
|
||||
dl_dir = bpy.path.abspath(dl_dir)
|
||||
if dl_dir != '':
|
||||
f.write("\n" + content_indent + "leenkx.network.torrent.TorrentClient.defaultDownloadDir = " + json.dumps(dl_dir) + ";")
|
||||
trackers_list = [json.dumps(t.name) for t in wrd.lnx_torrent_trackers if t.name != '']
|
||||
f.write("\n" + content_indent + "leenkx.network.torrent.TorrentClient.defaultTrackers = [" + ", ".join(trackers_list) + "];")
|
||||
ice_list = [json.dumps(t.name) for t in wrd.lnx_torrent_ice_servers if t.name != '']
|
||||
f.write("\n" + content_indent + "leenkx.network.torrent.peer.RtcPeerPool.defaultIceServers = [" + ", ".join(ice_list) + "];")
|
||||
f.write("\n" + content_indent + "leenkx.network.torrent.LeenkxClient.PEERTIMEOUT = " + str(wrd.lnx_torrent_peer_timeout) + ";")
|
||||
f.write("\n" + content_indent + "leenkx.network.torrent.LeenkxClient.defaultHeartbeat = " + str(wrd.lnx_torrent_heartbeat) + ";")
|
||||
|
||||
# Write Starter.main call
|
||||
starter_indent = content_indent + " "
|
||||
f.write("\n" + content_indent + "leenkx.system.Starter.main(")
|
||||
|
||||
Reference in New Issue
Block a user