mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
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:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user