add handling for web operator selection

where if user click on item in the table it gets selected in blender
This commit is contained in:
Ziad-I
2024-06-20 16:51:51 +03:00
committed by Dion Moult
parent 2738b280a1
commit d2a27999ba
3 changed files with 55 additions and 20 deletions
@@ -35,11 +35,10 @@ class WebNamespace(socketio.AsyncNamespace):
async def on_disconnect(self, sid):
print(f"Web client disconnected: {sid}")
async def on_operator(self, sid, data):
async def on_web_operator(self, sid, data):
print(f"Web client {sid} operator: {data}")
json_data = json.loads(data)
# TODO: need to add event listeners in blenderbim side for event web_operator
# await sio.emit("web_operator", json_data, namespace="/blender", room=json_data["blenderId"])
await sio.emit("web_operator", data["operator"], namespace="/blender", room=data["blenderId"])
# Blender namespace
@@ -50,6 +49,7 @@ class BlenderNamespace(socketio.AsyncNamespace):
async def on_connect(self, sid, environ):
print(f"Blender client connected: {sid}")
# Notify web client about new connection
blender_messages[sid] = {}
await sio.emit("blender_connect", sid, namespace="/web")
async def on_disconnect(self, sid):
@@ -59,21 +59,15 @@ class BlenderNamespace(socketio.AsyncNamespace):
del blender_messages[sid]
await sio.emit("blender_disconnect", sid, namespace="/web")
async def on_data(self, sid, data):
print(f"Data from Blender client {sid}: {data}")
# Store the message and forward it to the web client
blender_messages[sid] = data
await sio.emit("blender_data", {"blenderId": sid, "data": data}, namespace="/web")
async def on_default_data(self, sid, data):
print(f"Default data from Blender client {sid}: {data}")
# blender_messages[sid] = data
# blender_messages[sid]["default_data"] = data
# await sio.emit("default_data", {"blenderId": sid, "data": data}, namespace="/web")
async def on_csv_data(self, sid, data):
print(f"CSV data from Blender client {sid}:")
# Store the message and forward it to the web client
blender_messages[sid] = data
blender_messages[sid]["csv_data"] = data
await sio.emit("csv_data", {"blenderId": sid, "data": data}, namespace="/web")
@@ -4,8 +4,11 @@ $(document).ready(function () {
const socket = io(url);
console.log("socket: ", socket);
// keeps track of blenders connected in form of
// {shown:bool, filename:name}
const connectedClients = {};
// add a new talbe with data and filename
function addTableElement(blenderId, csvData, filename) {
const tableContainer = $("<div></div>")
.addClass("table-container")
@@ -36,21 +39,29 @@ $(document).ready(function () {
table.on("rowSelected", function (row) {
var index = row.getIndex(); // the guid of the object
// table id is usually "table-BlenderId" so blender id is always
// after the first 6 characters
var tableId = row.getTable().element.id.substr(6);
const msg = JSON.stringify({
operator_type: "selection",
const msg = {
blenderId: tableId,
guid: index,
});
socket.emit("operator", msg);
operator: {
type: "selection",
GlobalId: index,
},
};
socket.emit("web_operator", msg);
});
}
// update table and filename
function updateTableElement(blenderId, csvData, filename) {
// TODO: see if we can only replace updated rows only.
// TODO: and handle case where new columns are added
// for now just replace the data in the table
const table = Tabulator.findTable("#table-" + blenderId)[0];
if (table) {
table.replaceData(csvData, { importFormat: "csv" });
table.setData(csvData);
$("#title-" + blenderId).text(filename); // Update the title
}
}
+33 -3
View File
@@ -19,6 +19,7 @@
import bpy
from blenderbim.bim.module.web.data import WebData
import blenderbim.core.tool
import blenderbim.tool as tool
import socket
import os
import subprocess
@@ -26,11 +27,13 @@ import webbrowser
import asyncio
import socketio
import threading
import queue
from time import sleep
sio = None
ws_process = None
ws_thread = None
web_operator_queue = queue.Queue()
class Web(blenderbim.core.tool.Web):
@@ -81,6 +84,7 @@ class Web(blenderbim.core.tool.Web):
ws_url = f"ws://localhost:{port}/blender"
ws_thread.run_coro(cls.sio_connect(ws_url))
cls.set_is_connected(True)
bpy.app.timers.register(cls.check_operator_queue)
cls.send_default_webui_data()
@classmethod
@@ -130,6 +134,27 @@ class Web(blenderbim.core.tool.Web):
if ws_thread is not None and bpy.context.scene.WebProperties.is_connected:
ws_thread.run_coro(cls.sio_send(data, event, namespace))
@classmethod
def check_operator_queue(cls):
if not bpy.context.scene.WebProperties.is_connected:
with web_operator_queue.mutex:
web_operator_queue.queue.clear()
return None # unregister timer if not connected
while not web_operator_queue.empty():
operator_data = web_operator_queue.get_nowait()
if not operator_data:
continue
if operator_data["type"] == "selection":
bpy.ops.object.select_all(action="DESELECT")
guid = operator_data["GlobalId"]
ele = tool.Ifc.get().by_guid(guid)
obj = tool.Ifc.get_object(ele)
obj.select_set(True)
return 1.0
@classmethod
def open_web_browser(cls, port):
webbrowser.open(f"http://127.0.0.1:{port}/")
@@ -139,9 +164,7 @@ class Web(blenderbim.core.tool.Web):
await sio.connect(url, transports=["websocket"], namespaces="/blender")
# TODO: register event handlers to handle incoming messages
# sio.on("data", test.message_handler, namespace="/blender")
# await sio.emit("data", {"from": "client"}, namespace="/blender")
sio.on("web_operator", cls.sio_handle_web_operator, namespace="/blender")
@classmethod
async def sio_disconnect(cls):
@@ -151,6 +174,13 @@ class Web(blenderbim.core.tool.Web):
async def sio_send(cls, data, event="data", namespace="/blender"):
await sio.emit(event, data, namespace=namespace)
@classmethod
async def sio_handle_web_operator(cls, data):
try:
web_operator_queue.put_nowait(data)
except queue.Full:
pass
@classmethod
def set_is_running(cls, is_running):
bpy.context.scene.WebProperties.is_running = is_running