refactor: remove refesh session mecanism with client api calls to avoid UI freeze during heavy tasks upload
This commit is contained in:
43
client.py
43
client.py
@ -14,18 +14,18 @@ import zmq
|
|||||||
from . import helpers, message
|
from . import helpers, message
|
||||||
from .libs import dump_anything, umsgpack
|
from .libs import dump_anything, umsgpack
|
||||||
|
|
||||||
lock = threading.Lock()
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
CONNECT_TIMEOUT = 2
|
CONNECT_TIMEOUT = 2
|
||||||
|
WATCH_FREQUENCY = 0.1
|
||||||
WAITING_TIME = 0.001
|
WAITING_TIME = 0.001
|
||||||
SERVER_MAX = 1
|
SERVER_MAX = 1
|
||||||
DUMP_AGENTS_NUMBER = 1
|
DUMP_AGENTS_NUMBER = 1
|
||||||
|
|
||||||
|
lock = threading.Lock()
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
instance = None
|
instance = None
|
||||||
|
|
||||||
|
|
||||||
class State(Enum):
|
class State(Enum):
|
||||||
INITIAL = 1
|
INITIAL = 1
|
||||||
SYNCING = 2
|
SYNCING = 2
|
||||||
@ -61,10 +61,10 @@ class Client(object):
|
|||||||
self.ctx = zmq.Context()
|
self.ctx = zmq.Context()
|
||||||
self.pipe, peer = zpipe(self.ctx)
|
self.pipe, peer = zpipe(self.ctx)
|
||||||
self.store = {}
|
self.store = {}
|
||||||
|
|
||||||
self.serial_product = queue.Queue()
|
self.serial_product = queue.Queue()
|
||||||
self.serial_feed = queue.Queue()
|
self.serial_feed = queue.Queue()
|
||||||
self.stop_event = threading.Event()
|
self.stop_event = threading.Event()
|
||||||
|
|
||||||
# Net agent
|
# Net agent
|
||||||
self.net_agent = threading.Thread(
|
self.net_agent = threading.Thread(
|
||||||
target=net_worker,
|
target=net_worker,
|
||||||
@ -83,7 +83,7 @@ class Client(object):
|
|||||||
|
|
||||||
# Sync agent
|
# Sync agent
|
||||||
self.watchdog_agent = threading.Thread(
|
self.watchdog_agent = threading.Thread(
|
||||||
target=watchdog_worker, args=(self.serial_feed, 0.2, self.stop_event), name="watchdog-agent")
|
target=watchdog_worker, args=(self.serial_feed,WATCH_FREQUENCY, self.stop_event), name="watchdog-agent")
|
||||||
self.watchdog_agent.daemon = True
|
self.watchdog_agent.daemon = True
|
||||||
self.watchdog_agent.start()
|
self.watchdog_agent.start()
|
||||||
|
|
||||||
@ -147,7 +147,6 @@ class Client(object):
|
|||||||
self.serial_feed.put(('STOP', None, None))
|
self.serial_feed.put(('STOP', None, None))
|
||||||
|
|
||||||
# READ-ONLY FUNCTIONS
|
# READ-ONLY FUNCTIONS
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
"""Lookup value in distributed hash table
|
"""Lookup value in distributed hash table
|
||||||
Sends [GET][key] to the agent and waits for a value response
|
Sends [GET][key] to the agent and waits for a value response
|
||||||
@ -185,16 +184,24 @@ class Client(object):
|
|||||||
return dump_list
|
return dump_list
|
||||||
|
|
||||||
def state(self):
|
def state(self):
|
||||||
if not self.is_busy():
|
if self.net_agent is None or not self.net_agent.is_alive():
|
||||||
self.pipe.send_multipart([b"STATE"])
|
return 1 #State.INITIAL
|
||||||
try:
|
elif self.net_agent.is_alive() and self.store.keys():
|
||||||
reply = self.pipe.recv_multipart()
|
return 3 # State.ACTIVE
|
||||||
except KeyboardInterrupt:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
return umsgpack.unpackb(reply[0])
|
|
||||||
else:
|
else:
|
||||||
return None
|
return 2 #State.SYNCING
|
||||||
|
|
||||||
|
# # return self.state
|
||||||
|
# if not self.is_busy():
|
||||||
|
# self.pipe.send_multipart([b"STATE"])
|
||||||
|
# try:
|
||||||
|
# reply = self.pipe.recv_multipart()
|
||||||
|
# except KeyboardInterrupt:
|
||||||
|
# return
|
||||||
|
# else:
|
||||||
|
# return umsgpack.unpackb(reply[0])
|
||||||
|
# else:
|
||||||
|
# return None
|
||||||
|
|
||||||
|
|
||||||
class Server(object):
|
class Server(object):
|
||||||
@ -223,7 +230,7 @@ class ClientAgent(object):
|
|||||||
property_map = None
|
property_map = None
|
||||||
publisher = None
|
publisher = None
|
||||||
id = None
|
id = None
|
||||||
state = State.INITIAL
|
state = None
|
||||||
server = None
|
server = None
|
||||||
serial = None
|
serial = None
|
||||||
serialisation_agent = None
|
serialisation_agent = None
|
||||||
|
10
helpers.py
10
helpers.py
@ -72,7 +72,7 @@ def load(key, value):
|
|||||||
target = resolve_bpy_path(key)
|
target = resolve_bpy_path(key)
|
||||||
target_type = key.split('/')[0]
|
target_type = key.split('/')[0]
|
||||||
|
|
||||||
logger.info("load {}".format(key))
|
logger.debug("load {}".format(key))
|
||||||
if value == "None":
|
if value == "None":
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ def load_armature(target=None, data=None, create=False):
|
|||||||
target_new_b = target.edit_bones.new[eb]
|
target_new_b = target.edit_bones.new[eb]
|
||||||
dump_anything.load(target_new_b, data['bones'][eb])
|
dump_anything.load(target_new_b, data['bones'][eb])
|
||||||
|
|
||||||
logger.info(eb)
|
logger.debug(eb)
|
||||||
|
|
||||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
||||||
fp.close()
|
fp.close()
|
||||||
@ -330,7 +330,7 @@ def load_collection(target=None, data=None, create=False):
|
|||||||
target.children.link(
|
target.children.link(
|
||||||
bpy.data.collections[collection])
|
bpy.data.collections[collection])
|
||||||
else:
|
else:
|
||||||
logger.info(target.name)
|
logger.debug(target.name)
|
||||||
|
|
||||||
for collection in target.children.keys():
|
for collection in target.children.keys():
|
||||||
if collection not in data["children"]:
|
if collection not in data["children"]:
|
||||||
@ -371,14 +371,14 @@ def load_scene(target=None, data=None, create=False):
|
|||||||
|
|
||||||
# load collections
|
# load collections
|
||||||
# TODO: Recursive link
|
# TODO: Recursive link
|
||||||
logger.info("check for scene childs")
|
logger.debug("check for scene childs")
|
||||||
for collection in data["collection"]["children"]:
|
for collection in data["collection"]["children"]:
|
||||||
logger.debug(collection)
|
logger.debug(collection)
|
||||||
if collection not in target.collection.children.keys():
|
if collection not in target.collection.children.keys():
|
||||||
target.collection.children.link(
|
target.collection.children.link(
|
||||||
bpy.data.collections[collection])
|
bpy.data.collections[collection])
|
||||||
|
|
||||||
logger.info("check for scene child to remove")
|
logger.debug("check for scene child to remove")
|
||||||
for collection in target.collection.children.keys():
|
for collection in target.collection.children.keys():
|
||||||
if collection not in data["collection"]["children"]:
|
if collection not in data["collection"]["children"]:
|
||||||
target.collection.children.unlink(
|
target.collection.children.unlink(
|
||||||
|
53
operators.py
53
operators.py
@ -18,14 +18,11 @@ from .libs import umsgpack
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# client_instance = None
|
# client_instance = None
|
||||||
client_keys = None
|
|
||||||
client_state = 1
|
|
||||||
server = None
|
server = None
|
||||||
context = None
|
context = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def clean_scene(elements=helpers.BPY_TYPES.keys()):
|
def clean_scene(elements=helpers.BPY_TYPES.keys()):
|
||||||
for datablock in elements:
|
for datablock in elements:
|
||||||
datablock_ref =getattr(bpy.data, helpers.BPY_TYPES[datablock])
|
datablock_ref =getattr(bpy.data, helpers.BPY_TYPES[datablock])
|
||||||
@ -84,21 +81,8 @@ def init_datablocks():
|
|||||||
client.instance.set(key)
|
client.instance.set(key)
|
||||||
|
|
||||||
|
|
||||||
def refresh_session_data():
|
|
||||||
global client_keys, client_state
|
|
||||||
|
|
||||||
keys = client.instance.list()
|
|
||||||
|
|
||||||
if keys:
|
|
||||||
client_keys = keys
|
|
||||||
state = client.instance.state()
|
|
||||||
|
|
||||||
if state:
|
|
||||||
client_state = state
|
|
||||||
|
|
||||||
|
|
||||||
def default_tick():
|
def default_tick():
|
||||||
refresh_session_data()
|
|
||||||
upload_client_instance_position()
|
upload_client_instance_position()
|
||||||
|
|
||||||
return .2
|
return .2
|
||||||
@ -158,22 +142,6 @@ class SessionJoinOperator(bpy.types.Operator):
|
|||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
class SessionRefreshOperator(bpy.types.Operator):
|
|
||||||
bl_idname = "session.refresh"
|
|
||||||
bl_label = "refresh"
|
|
||||||
bl_description = "refresh client ui keys "
|
|
||||||
bl_options = {"REGISTER"}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def poll(cls, context):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def execute(self, context):
|
|
||||||
refresh_session_data()
|
|
||||||
|
|
||||||
return {"FINISHED"}
|
|
||||||
|
|
||||||
|
|
||||||
class SessionPropertyAddOperator(bpy.types.Operator):
|
class SessionPropertyAddOperator(bpy.types.Operator):
|
||||||
bl_idname = "session.add_prop"
|
bl_idname = "session.add_prop"
|
||||||
bl_label = "add"
|
bl_label = "add"
|
||||||
@ -279,7 +247,6 @@ class SessionStopOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
global server
|
global server
|
||||||
global client_keys, client_state
|
|
||||||
|
|
||||||
net_settings = context.window_manager.session
|
net_settings = context.window_manager.session
|
||||||
|
|
||||||
@ -295,9 +262,8 @@ class SessionStopOperator(bpy.types.Operator):
|
|||||||
# del client_instance
|
# del client_instance
|
||||||
|
|
||||||
# client_instance = None
|
# client_instance = None
|
||||||
client_keys = None
|
|
||||||
net_settings.is_admin = False
|
net_settings.is_admin = False
|
||||||
client_state = 1
|
|
||||||
|
|
||||||
unregister_ticks()
|
unregister_ticks()
|
||||||
draw.renderer.stop()
|
draw.renderer.stop()
|
||||||
@ -332,7 +298,6 @@ class SessionPropertyRightOperator(bpy.types.Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
global server
|
global server
|
||||||
global client_keys, client_state
|
|
||||||
|
|
||||||
net_settings = context.window_manager.session
|
net_settings = context.window_manager.session
|
||||||
|
|
||||||
@ -380,7 +345,6 @@ class SessionSnapUserOperator(bpy.types.Operator):
|
|||||||
# TODO: Rename to match official blender convention
|
# TODO: Rename to match official blender convention
|
||||||
classes = (
|
classes = (
|
||||||
SessionJoinOperator,
|
SessionJoinOperator,
|
||||||
SessionRefreshOperator,
|
|
||||||
SessionPropertyAddOperator,
|
SessionPropertyAddOperator,
|
||||||
SessionPropertyGetOperator,
|
SessionPropertyGetOperator,
|
||||||
SessionStopOperator,
|
SessionStopOperator,
|
||||||
@ -392,8 +356,6 @@ classes = (
|
|||||||
|
|
||||||
|
|
||||||
def is_replicated(update):
|
def is_replicated(update):
|
||||||
# global client_keys
|
|
||||||
# dickt = dict(client_keys)
|
|
||||||
object_type = update.id.bl_rna.__class__.__name__
|
object_type = update.id.bl_rna.__class__.__name__
|
||||||
object_name = update.id.name
|
object_name = update.id.name
|
||||||
|
|
||||||
@ -409,7 +371,7 @@ def is_replicated(update):
|
|||||||
if client.instance.exist(key):
|
if client.instance.exist(key):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.info("{} Not rep".format(key))
|
logger.debug("{} Not rep".format(key))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -435,17 +397,14 @@ def toogle_update_dirty(context, update):
|
|||||||
data_ref = get_datablock_from_update(update,context)
|
data_ref = get_datablock_from_update(update,context)
|
||||||
|
|
||||||
if data_ref:
|
if data_ref:
|
||||||
logger.info(update.id.bl_rna.__class__.__name__)
|
logger.debug(update.id.bl_rna.__class__.__name__)
|
||||||
data_ref.is_dirty= True
|
data_ref.is_dirty= True
|
||||||
|
|
||||||
|
|
||||||
def depsgraph_update(scene):
|
def depsgraph_update(scene):
|
||||||
global client_keys
|
|
||||||
global client_state
|
|
||||||
|
|
||||||
ctx = bpy.context
|
ctx = bpy.context
|
||||||
|
|
||||||
if client_state == 3:
|
if client.instance.state() == 3:
|
||||||
|
|
||||||
if ctx.mode in ['OBJECT','PAINT_GPENCIL']:
|
if ctx.mode in ['OBJECT','PAINT_GPENCIL']:
|
||||||
updates = ctx.view_layer.depsgraph.updates
|
updates = ctx.view_layer.depsgraph.updates
|
||||||
@ -496,7 +455,6 @@ def register():
|
|||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
global server
|
global server
|
||||||
global client_keys
|
|
||||||
|
|
||||||
draw.unregister()
|
draw.unregister()
|
||||||
|
|
||||||
@ -511,7 +469,6 @@ def unregister():
|
|||||||
if client.instance:
|
if client.instance:
|
||||||
client.instance.exit()
|
client.instance.exit()
|
||||||
client.instance = None
|
client.instance = None
|
||||||
del client_keys
|
|
||||||
|
|
||||||
from bpy.utils import unregister_class
|
from bpy.utils import unregister_class
|
||||||
for cls in reversed(classes):
|
for cls in reversed(classes):
|
||||||
|
BIN
test.blend
BIN
test.blend
Binary file not shown.
24
ui.py
24
ui.py
@ -1,6 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
|
from . import client
|
||||||
from . import client, operators
|
from . import operators
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
window_manager = context.window_manager
|
window_manager = context.window_manager
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
if operators.client_state == 1:
|
if not client.instance or (client.instance and client.instance.state() == 1):
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
box = row.box()
|
box = row.box()
|
||||||
row = box.row()
|
row = box.row()
|
||||||
@ -75,7 +75,7 @@ class SESSION_PT_settings(bpy.types.Panel):
|
|||||||
row.operator("session.join", text="CONNECT")
|
row.operator("session.join", text="CONNECT")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if operators.client_state == 3:
|
if client.instance.state() == 3:
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.operator("session.stop", icon='QUIT', text="Exit")
|
row.operator("session.stop", icon='QUIT', text="Exit")
|
||||||
@ -107,7 +107,7 @@ class SESSION_PT_user(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return operators.client_state == 3
|
return client.instance and client.instance.state() == 3
|
||||||
|
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
@ -117,8 +117,9 @@ class SESSION_PT_user(bpy.types.Panel):
|
|||||||
scene = context.window_manager
|
scene = context.window_manager
|
||||||
# Create a simple row.
|
# Create a simple row.
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
if operators.client_keys and len(operators.client_keys) > 0:
|
client_keys = client.instance.list()
|
||||||
for key in operators.client_keys:
|
if client_keys and len(client_keys) > 0:
|
||||||
|
for key in client_keys:
|
||||||
if 'Client' in key[0]:
|
if 'Client' in key[0]:
|
||||||
info = ""
|
info = ""
|
||||||
item_box = row.box()
|
item_box = row.box()
|
||||||
@ -152,7 +153,7 @@ class SESSION_PT_properties(bpy.types.Panel):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return operators.client_state == 3
|
return client.instance and client.instance.state() == 3
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
@ -174,11 +175,10 @@ class SESSION_PT_properties(bpy.types.Panel):
|
|||||||
|
|
||||||
# Property area
|
# Property area
|
||||||
area_msg = row.box()
|
area_msg = row.box()
|
||||||
area_msg.operator("session.refresh", text="",
|
client_keys = client.instance.list()
|
||||||
icon="UV_SYNC_SELECT")
|
if client_keys and len(client_keys) > 0:
|
||||||
if operators.client_keys and len(operators.client_keys) > 0:
|
|
||||||
|
|
||||||
for item in sorted(operators.client_keys, key=get_client_key):
|
for item in sorted(client_keys, key=get_client_key):
|
||||||
owner = 'toto'
|
owner = 'toto'
|
||||||
try:
|
try:
|
||||||
owner = item[1]
|
owner = item[1]
|
||||||
|
Reference in New Issue
Block a user