### Get Object Children and Hierarchy in JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Navigates the digital twin object hierarchy to access children, parents, siblings, and spatial relationships. It provides specific actions to retrieve these hierarchical links efficiently. ```javascript const getChildrenAction = new sm_action_get_objects_children(); const getParentAction = new sm_action_get_objects_parent(); const getSiblingsAction = new sm_action_get_objects_brothers(); // Get all children of an object const assembly = THING.App.current.query('#motor_assembly')[0]; getChildrenAction.update(assembly); const children = getChildrenAction.getParam(); console.log('Assembly has', children.length, 'children'); // Get parent object const component = THING.App.current.query('#rotor_01')[0]; getParentAction.update(component); const parent = getParentAction.getParam(); console.log('Component parent:', parent.name); // Get sibling objects getSiblingsAction.update(component); const siblings = getSiblingsAction.getParam(); console.log('Component has', siblings.length, 'siblings'); // Get spatial parent (different from hierarchy parent) const getSpatialParentAction = new sm_action_get_objects_space_parent(); const device = THING.App.current.query('#device_01')[0]; getSpatialParentAction.update(device); const spatialParent = getSpatialParentAction.getParam(); console.log('Device spatial parent:', spatialParent.name); ``` -------------------------------- ### Lerp Opacity Function with Effects Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md The lerpOpacityFun function handles the smooth transition of an object's opacity using a lerping mechanism. It stops any existing lerp operations on 'sm_lerp_opacity', resets opacity if a 'pingpong' or 'repeat' loop type was used previously, and then initiates a new lerp operation. The opacity is transitioned from a starting value (mFrom) to an ending value (mTo) over a specified duration (time), utilizing defined lerp and loop types. The update callback ensures the opacity is applied correctly using `uinv.utils.ex.setObjOpacity`. ```javascript function lerpOpacityFun(obj) { obj.stopLerpTo('sm_lerp_opacity'); if (obj.lerpbefore) { if (obj.lerpbefore.type === 'pingpong' || obj.lerpbefore.type === 'repeat') { obj.style.opacity = obj.lerpbefore.oldopacity; } } obj.lerpbefore = { type: mLoopType, oldopacity: obj.style.opacity }; obj.lerpTo({ from: { 'style/opacity1': Number(mFrom) / 100 }, to: { 'style/opacity1': Number(mTo) / 100 }, time: time, delayTime: 0, lerpType: getLerpTypeByString(mLerpType), loopType: mLoopType, complete() {}, update() { uinv.utils.ex.setObjOpacity(obj, obj.style.opacity1, { name: '孪生体渐变透明', priority: 11, traverse: true }); // eslint-disable-next-line no-undef // THINGX.Debug.setLevel('error'); // console.error('更新'); }, stop() {}, }, 'sm_lerp_opacity'); } ``` -------------------------------- ### Loop Through Sub-Nodes in JavaScript Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This method processes sub-nodes, first getting child elements and then filtering them against the existing sub-nodes of the parent object. It ensures that only relevant sub-nodes are processed and pushed. Dependencies: 'getChild', 'pushElementToExplodedObj'. ```javascript objSubNodesLoop(objSubNodes, obj, orderNumber) { const tempC = this.getChild(obj, objSubNodes); const subN = Array.from(obj.subNodes); const _this = this; subN.filter(v => tempC.some(vv => v.name === vv.name)).forEach(item => { _this.pushElementToExplodedObj(orderNumber, item); }); } ``` -------------------------------- ### Get Digital Twin Attributes with JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Retrieves attribute values from digital twin objects. Supports accessing both built-in properties and custom user-defined attributes. Requires the 'sm_action_object_get_attribute' plugin. ```javascript // Initialize attribute getter plugin const getAttrAction = new sm_action_object_get_attribute(); // Get custom attribute getAttrAction.mName = 'temperature'; const turbine = THING.App.current.query('#turbine_01')[0]; turbine.setAttribute('temperature', 850); getAttrAction.update(turbine); const temperature = getAttrAction.getParam(); // Get monitor data attribute turbine.setAttribute('MONITOR/_/_/rpm', 3600); getAttrAction.mName = 'MONITOR/_/_/rpm'; getAttrAction.update(turbine); const rpm = getAttrAction.getParam(); // Get user data attribute turbine.setAttribute('userData/DATA/efficiency', 94.5); getAttrAction.mName = 'userData/DATA/efficiency'; getAttrAction.update(turbine); const efficiency = getAttrAction.getParam(); console.log('Temperature:', temperature, '°C'); console.log('RPM:', rpm); console.log('Efficiency:', efficiency, '%'); // Output: Temperature: 850 °C // Output: RPM: 3600 // Output: Efficiency: 94.5 % ``` -------------------------------- ### Get First Level Node Children in JavaScript Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Retrieves the first level of children for a 'node' type, applying filtering via 'noElement' if provided. This function is specific to handling 'node' structures. Dependencies: 'getChild'. ```javascript levelNodeOrder(obj, noElement) { if (obj.node.children.length) { const subNodes = this.getChild(obj, obj.node.children); return noElement ? subNodes.filter(item => !noElement.includes(item.name)) : subNodes; } } ``` -------------------------------- ### Get Surrounding Digital Twin Objects in JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Queries digital twin objects within a specified radius from a target object. This is useful for proximity detection and spatial queries. It allows configuration of the maximum number of objects to return and the search radius. ```javascript const surroundingAction = new sm_action_get_objects_around(); // Configure search parameters surroundingAction.mNum = 10; // Maximum number of objects to return surroundingAction.mRange = 50; // Search radius in scene units // Find objects around a central point const centerObject = THING.App.current.query('#sensor_hub')[0]; surroundingAction.update(centerObject); const nearbyObjects = surroundingAction.getParam(); console.log('Found', nearbyObjects.length, 'objects within 50 units'); nearbyObjects.forEach(obj => { const distance = THING.Math.getDistance( centerObject.position, obj.position ); console.log(`- ${obj.name}: ${distance.toFixed(2)} units away`); }); // Use case: Find all equipment near a maintenance station surroundingAction.mNum = 20; surroundingAction.mRange = 100; const maintenanceStation = THING.App.current.query('#maintenance_01')[0]; surroundingAction.update(maintenanceStation); const equipmentToService = surroundingAction.getParam(); ``` -------------------------------- ### Get Child Nodes with Filtering (JavaScript) Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Retrieves child nodes from a given parent, filtering out elements that are decorators and specifically selecting children of the 'Root Scene' if present. If no 'Root Scene' children are found, it returns the original children list. This function is used to obtain relevant child elements for processing. ```javascript // 获取孩子节点 getChild(obj, children) { let tempC = []; const _this = this; tempC = children.filter(ele => !_this.isObjDecorator(obj, ele)) .filter(ele => ele.name === 'Root Scene') .flatMap(ele => ele.children[0].children); return !tempC.length ? children : tempC; } ``` -------------------------------- ### Get First Level Children (Object Type) in JavaScript Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Retrieves the direct children of an 'obj' type, optionally filtering them based on a 'noElement' list. This function is used for obtaining the immediate child elements of an object. Dependencies: 'getElementByNOElement'. ```javascript levelOrder(data, noElement) { if (data.children.length) { return noElement ? this.getElementByNOElement(data.children, noElement) : data.children; } } ``` -------------------------------- ### Get Lerp Type by String Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This function maps string representations of lerp (linear interpolation) types to their corresponding enum values within the THING.LerpType object. It supports various easing functions like Elastic, Back, and Bounce, with 'in', 'out', and 'inout' variations. If an unknown type is provided, it defaults to Linear.None. ```javascript function getLerpTypeByString(mLerpType) { switch (mLerpType) { case 'elastic.in': return THING.LerpType.Elastic.In; case 'elastic.out': return THING.LerpType.Elastic.Out; case 'elastic.inout': return THING.LerpType.Elastic.InOut; case 'back.in': return THING.LerpType.Back.In; case 'back.out': return THING.LerpType.Back.Out; case 'back.inout': return THING.LerpType.Back.InOut; case 'bounce.in': return THING.LerpType.Bounce.In; case 'bounce.out': return THING.LerpType.Bounce.Out; case 'bounce.inout': return THING.LerpType.Bounce.InOut; default: return THING.LerpType.Linear.None; } }; ``` -------------------------------- ### Handle Video Playback and RTSP URLs Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This snippet handles video playback by checking the loop type and static URL. It supports .m3u8 streams for RTSP and other video formats. It also includes logic for handling RTSP, GB server URLs, and creating projectors. ```javascript if (this.mLoopType == '使用视频播放地址') { this.staticUrl0 = obj.getAttribute(this.staticUrl); if (this.staticUrl0.includes('.m3u8')) { this.RTSPUrl0 = this.staticUrl0; this.CreateProjector(app, obj, this.Priority); } else { this.ctVideoArea(obj); } } if (this.mLoopType !== '使用视频播放地址') { this.CreateProjector(app, obj, this.Priority); } if (this.mLoopType == '使用视频播放地址' && this.staticUrl.includes('userData')) { const staticUrl0 = obj.getAttribute(this.staticUrl); this.staticUrl0 = uinv.utils.getResourceUrl(staticUrl0); if (this.staticUrl0.includes('.m3u8')) { this.RTSPUrl0 = this.staticUrl0; this.CreateProjector(app, obj, this.Priority); } else { this.ctVideoArea(obj); } } else if ((this.RTSPUrl.includes('rtsp') || this.GbEquipmentUrl.includes('000') || this.GbChannelUrl.includes('000')) && this.mLoopType !== '使用接口数据') { this.RTSPUrl0 = this.RTSPUrl; this.GbEquipmentUrl0 = this.GbEquipmentUrl; this.GbChannelUrl0 = this.GbChannelUrl; const app = THING.App.current; this.CreateProjector(app, obj, this.Priority); } else if ((this.mLoopType == '使用视频播放地址' && this.staticUrl.includes('http')) || (this.mLoopType == '使用视频播放地址' && this.staticUrl !== '' && this.staticUrl.includes('.mp4'))) { this.staticUrl0 = uinv.utils.getResourceUrl(this.staticUrl); if (this.staticUrl0.includes('.m3u8')) { this.RTSPUrl0 = this.staticUrl0; this.CreateProjector(app, obj, this.Priority); } else { this.ctVideoArea(obj); } } ``` -------------------------------- ### Query Current Space Data with API Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Fetches device list data for the current space based on query criteria. It determines the scene ID based on the current environment ('园区' or otherwise) and queries the API for device information. Returns a Promise that resolves when data is fetched or if no criteria are met. ```javascript function currentSpaceFun(_this){ thingObj = app.level._current; oldData = Array.from(thingObj.query(queryCriteria, false)); if (_this.judgmentScenario(thingObj) === '园区'){ if (thingObj.type === 'Campus') { InterfaceCiData.queryBean.sceneId = thingObj.userData._PJDBID_; } else { const campusObj = thingObj.parents.filter(item => item.type === 'Campus')[0]; InterfaceCiData.queryBean.sceneId = campusObj.userData._PJDBID_; } } else { InterfaceCiData.queryBean.sceneId = app.query('.GeoBasePoint')[0].userData._PJDBID_; } InterfaceCiData.queryBean.levelId = thingObj.userData._DBID_; return new Promise((resolve, reject) => { if (InterfaceCiData.queryBean.classNames.length || InterfaceCiData.queryBean.orAttrs.length) { uinv.utils.Api.assets.getDeviceList(InterfaceCiData).then(res => { if (res.code === -1) { if (thingObj.id == 'earthRoot'){ newData = res.data.ciDetailInfos.filter(item => item.ciMap._PARENT_ === thingObj.id || thingObj.id == 'earthRoot'); } else { newData = res.data.ciDetailInfos.filter(item => item.ciMap._PARENT_ === thingObj.id); } resolve(true); } }); } else { newData = []; } }); } ``` -------------------------------- ### Get Object Radius in JavaScript Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This function retrieves the radius of an object. If the radius is not already stored in `obj.userData.radius`, it calculates it using `calculateBoundingSphereRadius` and caches it for future use. This avoids redundant calculations. ```javascript getRadius(obj) { if (!obj.userData.radius) { obj.userData.radius = this.calculateBoundingSphereRadius(obj); } return obj.userData.radius; } ``` -------------------------------- ### Query Current Space and Below Data with API Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Retrieves device list data for the current space and all nested spaces. It sets the scene ID based on the environment ('园区' or otherwise) and queries the API. Handles cases where no class names or attributes are specified, resulting in an empty data set. ```javascript function currentSpaceAndBelow(_this){ thingObj = app.level._current; InterfaceCiData.queryBean.levelId = thingObj.userData._DBID_; return new Promise((resolve, reject) => { if (_this.judgmentScenario(thingObj) === '园区'){ oldData = Array.from(thingObj.query(queryCriteria)); InterfaceCiData.queryBean.sceneId = app.query('.Campus')[0].userData._PJDBID_; if (InterfaceCiData.queryBean.classNames.length || InterfaceCiData.queryBean.orAttrs.length) { uinv.utils.Api.assets.getDeviceList(InterfaceCiData).then(res => { if (res.code === -1) { newData = res.data.ciDetailInfos; resolve(); } }); } else { newData = []; } } else { InterfaceCiData.queryBean.sceneId = app.query('.GeoBasePoint')[0].userData._PJDBID_; oldData = Array.from(thingObj.query(queryCriteria)).filter(item => item.type == 'GeoBasePoint'); if (InterfaceCiData.queryBean.classNames.length || InterfaceCiData.queryBean.orAttrs.length) { uinv.utils.Api.assets.getDeviceList(InterfaceCiData).then(res => { if (res.code === -1) { newData = res.data.ciDetailInfos; resolve(); } }); } else { newData = []; } } }); } ``` -------------------------------- ### JavaScript: Resizing and Scaling DOM Elements Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This snippet handles the dynamic resizing and scaling of DOM elements. It calculates scale factors based on original dimensions and current viewport size, applying transformations to adjust the element's appearance. It also includes event listeners for window resize events to maintain scaling. Dependencies include standard browser DOM APIs. ```javascript zoomHeightNum = this.zoomHeight.replace(BFB, ''); } else if (this.zoomHeight.includes('px')) { zoomHeightNum = this.zoomHeight.replace(PX, ''); } const scaleWidth = width / zoomWidthNum || 1; const scaleHeight = height / zoomHeightNum || 1; dom.style.height = this.zoomHeight; dom.style.width = this.zoomWidth; dom.style.transform = `scale(${scaleWidth},${scaleHeight})`; dom.style.transformOrigin = `top left`; if (resizeConfig.length) { const resizeHandler = () => { const curWidth = resizeConfig[0] ? document.body.offsetWidth * resizeConfig[0] / 100 : width; const curHeight = resizeConfig[1] ? document.body.offsetHeight * resizeConfig[1] / 100 : height; const scaleWidth = curWidth / zoomWidthNum || 1; const scaleHeight = curHeight / zoomHeightNum || 1; dom.style.transform = `scale(${scaleWidth},${scaleHeight})`; }; window.addEventListener('resize', resizeHandler); dom.release = () => { window.removeEventListener('resize', resizeHandler); }; } } else { domIframe.style.height = '100%'; domIframe.style.width = '100%'; domIframe.style.transform = `scale(1)`; } ``` -------------------------------- ### JavaScript Video Fusion Action Implementation Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Implements the 'sm_action_VideoFusion' class for activating and managing video fusion. It handles updating video streams based on various inputs like RTSP URLs, monitoring data, or static URLs. Dependencies include the 'THING' library and potentially 'uinv' for utility functions. It dynamically creates projectors and sets video sources, with logic for handling real-time data updates and error conditions. ```javascript window.exactions=[ { handleStr: "sm_action_VideoFusion", caption: "激活视频融合", VERSION: "1.1.0", type: "sm_action", treeNode: ["高级相关"], handle: class extends sm_action { constructor(...t) { t[0] = "sm_action_VideoFusion", super(...t), this.staticUrl = "", this.RTSPUrl = "", this.GbEquipmentUrl = "", this.GbChannelUrl = "", this.Priority = "", this.mon = !1, this.RTSPUrl0 = "", this.GbEquipmentUrl0 = "", this.GbChannelUrl0 = "", this.onlinetime = "", this.onlineurl = "", this._isPromise = !0 } update(t) { return super.update(t), console.log(t, "obj"), new Promise((e, i) => { if (window.VideoFusion = [], Array.isArray(t) || t instanceof THING.Selector) for (let e = 0; e < t.length; e += 1) { if (this.RTSPUrl.includes("MONITOR") || this.GbEquipmentUrl.includes("MONITOR") || this.GbChannelUrl.includes("MONITOR")) { t[e].userData && t[e].userData._DBID_ && (uinv.monitorManager.remoteData(t[e].userData._DBID_), uinv.actionMonitorManager.remoteData(t[e].userData._DBID_)); const i = () => { if (t.MONITOR) for (let e in t.MONITOR._._) console.log(e), "设备编号" == e ? this.GbEquipmentUrl0 = t.MONITOR._._[e].value : "RTSP地址" == e ? this.RTSPUrl0 = t.MONITOR._._[e].value : "通道编号" == e && (this.GbChannelUrl0 = t.MONITOR._._[e].value ); }; THING.App.current.on("MONITOR_MANAGER_UPDATE_OK", null, i, "刷新数据") } else { if (this.RTSPUrl && this.RTSPUrl.includes("userData")) { const i = t[e].getAttribute(this.RTSPUrl); this.RTSPUrl0 = i, console.log(this.RTSPUrl0 + "[e]") } if (this.GbEquipmentUrl && this.GbEquipmentUrl.includes("userData")) { const i = t[e].getAttribute(this.GbEquipmentUrl); this.GbEquipmentUrl0 = i } if (this.GbChannelUrl && this.GbChannelUrl.includes("userData")) { const i = t[e].getAttribute(this.GbChannelUrl); this.GbChannelUrl0 = i } } if (this.staticUrl) this.ctVideoArea(t[e], this.Priority + e); else if (this.RTSPUrl.includes("rtsp") || this.GbEquipmentUrl.includes("000") || this.GbChannelUrl.includes("000")) { this.RTSPUrl0 = this.RTSPUrl, this.GbEquipmentUrl0 = this.GbEquipmentUrl, this.GbChannelUrl0 = this.GbChannelUrl; const i = THING.App.current; this.CreateProjector(i, t[e], this.Priority + e), console.log(this.RTSPUrl, "this.RTSPUrl"), this.RTSPUrl0 = "", this.GbEquipmentUrl0 = "", this.GbChannelUrl0 = "", console.log(this.RTSPUrl, "this.RTSPUrl0000") } this.onlineurl && uinv.utils.timer.regTimerFunc("onlineUrl", this.onlinetime, !0, async () => { console.info("3s 后执行一次"); const i = await fetch(this.onlineurl, { method: "post", headers: { "content-type": "application/json" } }), r = await i.json(); console.log(r, "response"), r.data.map(i => { i.ID == t[e].id && (console.log(t[e], "匹配上了"), "" != i.URL ? (this.staticUrl = i.URL, this.ctVideoArea(t[e], this.Priority + e)) : "" == i.URL && i.RTSP ? (this.RTSPUrl0 = i.RTSP, this.CreateProjector(app, t[e], this.Priority + e)) : "" == i.URL && "" == i.RTSP && i.Gb && (this.GbChannelUrl0 = i.Gb.GbChannelUrl, this.GbEquipmentUrl0 = i.Gb.GbEquipmentUrl, this.CreateProjector(app, t[e], this.Priority + e))) }) }) } else if (t instanceof THING.BaseObject) { if (this.RTSPUrl.includes("MONITOR") || this.GbEquipmentUrl.includes("MONITOR") || this.GbChannelUrl.includes("MONITOR")) { t.userData && t.userData._DBID_ && (uinv.monitorManager.remoteData(t.userData._DBID_), uinv.actionMonitorManager.remoteData(t.userData._DBID_)); const e = () => { if (t.MONITOR) for (let e in t.MONITOR._._) console.log(e), "设备编号" == e ? this.GbEquipmentUrl0 = t.MONITOR._._[e].value : "RTSP地址" == e ? this.RTSPUrl0 = t.MONITOR._._[e].value : "通道编号" == e && (this.GbChannelUrl0 = t.MONITOR._._[e].value ); }; THING.App.current.on("MONITOR_MANAGER_UPDATE_OK", null, e, "刷新数据") } else { if (this.RTSPUrl && this.RTSPUrl.includes("userData")) { const e = t.getAttribute(this.RTSPUrl); this.RTSPUrl = e } if (this.GbEquipmentUrl && this.GbEquipmentUrl.includes("userData")) { const e = t.getAttribute(this.GbEquipmentUrl); this.GbEquipmentUrl = e } if (this.GbChannelUrl && this.GbChannelUrl.includes("userData")) { const e = t.getAttribute(this.GbChannelUrl); this.GbChannelUrl = e } } if (this.staticUrl) this.ctVideoArea(t); else if (this.RTSPUrl.includes("rtsp") || this.GbEquipmentUrl.includes("000") || this.GbChannelUrl.includes("000")) { this.RTSPUrl0 = this.RTSPUrl, this.GbEquipmentUrl0 = this.GbEquipmentUrl, this.GbChannelUrl0 = this.GbChannelUrl; const e = THING.App.current; this.CreateProjector(e, t, this.Priority), console.log(this.RTSPUrl, "this.RTSPUrl") } this.onlineurl && uinv.utils.timer.regTimerFunc("onlinUrl2", this.onlinetime, !0, async () => { console.info("3s 后执行一次onlinUrl2"); const e = await fetch(this.onlineurl, { method: "post", headers: { "content-type": "application/json" } }), i = await e.json(); console.log(i, "response"), i.data.map((e, i) => { if (e.ID == t.id) { console.log(t, "匹配上了"); const i = THING.App.current; "" != e.URL ? (this.staticUrl = e.URL, this.ctVideoArea(t)) : "" == e.URL && (e.RTSP || e.Gb) && (this.RTSPUrl0 = e.RTSP, "" != e.Gb.GbChannelUrl && (this.GbChannelUrl0 = e.Gb.GbChannelUrl, this.GbEquipmentUrl0 = e.Gb.GbEquipmentUrl), this.CreateProjector(i, t, this.Priority)) } }) }) } }) } ctVideoArea(t, e) { const { position: i, angles: r } = t, n = THING.App.current.create({ type: "Projector", name: e || this.Priority, position: i, angles: [0, 180, 0, "XYZ"], parent: t, debug: !1 }), l = [t.floor]; n.setReceiveObjects(l), n.setVideo(this.staticUrl), n.far = 999, n.fov = 40, n.near = .2, n.culling = !0, n.cullingBias = -2e-5, n.autoUpdateCulling = !0 } CreateProjector(t, e, i) { const { position: r, angles: n } = e, l = ``` -------------------------------- ### Set Digital Twin Transparency with JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Controls object transparency, supporting immediate and gradual transitions. It utilizes sm_action_object_opacity and sm_action_object_opacity_gradient plugins. Input can be a single object or multiple objects queried by ID or class. Outputs the updated object's opacity style. Supports callbacks and cancellation. ```javascript const transparencyAction = new sm_action_object_opacity(); const gradualTransparencyAction = new sm_action_object_opacity_gradient(); transparencyAction.mOpacity = 0.5; transparencyAction.mName = 'fade'; const glass = THING.App.current.query('#glass_panel')[0]; transparencyAction.update(glass); gradualTransparencyAction.mOpacity = 0.2; gradualTransparencyAction.delayTime = 0; gradualTransparencyAction.continueTime = 2000; gradualTransparencyAction.mName = 'fadeOut'; gradualTransparencyAction.loopType = 'no'; gradualTransparencyAction.completeCallBack = true; const walls = THING.App.current.query('.wall'); gradualTransparencyAction.update(walls).then(() => { console.log('Transparency transition completed'); }); const cancelTransparency = new sm_action_object_unset_opacity_gradient(); cancelTransparency.mName = 'fadeOut'; cancelTransparency.update(walls); console.log('Glass opacity:', glass.style.opacity); ``` -------------------------------- ### Create Digital Twin Object Dynamically (JavaScript) Source: https://context7.com/uinosoft/plugins-resource/llms.txt Dynamically creates new 3D digital twin objects with configurable properties, spatial hierarchy, and custom attributes. This plugin returns a promise that resolves upon successful object loading. It requires THING.js and takes object configuration as input. ```javascript const createAction = new sm_action_object_create_thing(); createAction.mId = 'machine_001'; createAction.mName = 'Industrial Robot Arm'; createAction.modelurl = { path: '/models/robot_arm.gltf' }; createAction.mBelonging = 'factory_floor'; createAction.mVisible = true; createAction.selfAttribute = [ { params: { key: { _t: 'const', _v: 'serialNumber' }, value: { _t: 'const', _v: 'RBT-2024-001' } } }, { params: { key: { _t: 'const', _v: 'status' }, value: { _t: 'const', _v: 'operational' } } } ]; createAction.update(null).then(() => { const newObject = THING.App.current.query('#machine_001')[0]; console.log('Object created:', newObject.name); console.log('Serial Number:', newObject.getAttribute('serialNumber')); }); ``` -------------------------------- ### Get Level-Specific Children (Object Type) in JavaScript Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Filters children of an 'obj' type at a specific level, excluding elements present in the 'noElement' array. This is useful for targeted selection of child nodes. Dependencies: None explicitly stated, relies on standard array methods. ```javascript levelSubNodeOrder(data, noElement) { return noElement && data.children.length ? data.children.filter(item => !noElement.includes(item.name)) : data.children; } ``` -------------------------------- ### Set Gradient Color Effects on Digital Twins with JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Applies gradient color transitions to objects using the sm_action_object_colour_gradient plugin. Features customizable color, timing, loop modes, traversal, priority, and completion callbacks. Supports application to single or multiple objects and cancellation of animations. Returns a promise that resolves on completion. ```javascript const gradientAction = new sm_action_object_colour_gradient(); gradientAction.mColour = '#FF00FF'; gradientAction.delayTime = 500; gradientAction.continueTime = 3000; gradientAction.loopType = 'pingpong'; gradientAction.mName = 'pulse'; gradientAction.whetherToTraverse = true; gradientAction.priority = 2; gradientAction.completeCallBack = true; const reactor = THING.App.current.query('#reactor_core')[0]; gradientAction.update(reactor).then(() => { console.log('Gradient animation cycle completed'); }); gradientAction.mColour = '#00FF00'; gradientAction.loopType = 'restart'; const statusLights = THING.App.current.query('.status-light'); gradientAction.update(statusLights); const cancelGradient = new sm_action_object_unset_colour_gradient(); cancelGradient.mName = 'pulse'; cancelGradient.update(reactor); ``` -------------------------------- ### JavaScript: Implement 'sm_action_by_attribute_runaction' for Attribute-Based Actions Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This JavaScript class, 'sm_action_by_attribute_runaction', extends 'sm_action' to enable running action sets based on object attributes or JSON data. It handles attribute processing, variable writing, and action execution, supporting conditional logic and promises for asynchronous operations. Dependencies include the 'sm_manager' and 'THING' objects. ```javascript /* eslint-disable no-undef */ /* eslint-disable camelcase */ window.exactions = [{ handleStr: 'sm_action_by_attribute_runaction', caption: '依据属性运行操作集', version: 2.4, type: 'action_with_save', treeNode: ['条件判断'], handle: class sm_action_by_attribute_runaction extends sm_action { constructor(...args) { args[0] = 'sm_action_by_attribute_runaction'; super(...args); this.twinSource = 'twinAttribute'; this.jsonContent = ''; this.stringOrNumber = ''; this.strictMode = false; this._isPromise = true; this.selfAttribute = []; } selfAttributeProcess (selfAttributes) { const e = []; if (selfAttributes.length) { return selfAttributes.forEach((selfAttribute, a) => { e.push({}); ['mDuration', 'mLoopType', 'mDuraData', 'actionname', 'actionObj', 'variableName', 'variableValue'].forEach(n => { if (selfAttribute.params[n]){ if (selfAttribute.params[n]._t === 'variable') { e[a][n] = this.getParam(selfAttribute.params[n]._vu); } else if (selfAttribute.params[n]._t === 'const') { e[a][n] = selfAttribute.params[n]._v; } } } ); }), e; } return e; } writeVariable (actionname, variableName, variableValue) { if (sm_manager.mInstanceMap[actionname]) { const actionInstance = sm_manager.mInstanceMap[actionname]; if (variableName.trim()) { actionInstance.mVariable.mParams[variableName] = variableValue; } } } runActionFun (item) { const { actionname, actionObj, variableName, variableValue } = item; let actionnameArr = []; if (typeof (actionname) == 'string') { actionnameArr = actionname.trim().split(','); } if (actionObj instanceof THING.BaseObject) { actionnameArr.forEach(item => { this.writeVariable(item, variableName, variableValue); sm_manager.run(item, actionObj); }); } else if (Array.isArray(actionObj) || actionObj instanceof THING.Selector) { actionObj.forEach((objItem) => { actionnameArr.forEach(item => { this.writeVariable(item, variableName, variableValue); sm_manager.run(item, objItem); }); }); } else { actionnameArr.forEach(item => { this.writeVariable(item, variableName, variableValue); sm_manager.run(item, null); }); } } update (obj) { super.update(); try { if (this.strictMode) { if (this._isPromise === true) { return new Promise((resolve, reject) => { this.selfAttributeProcess(this.selfAttribute).map(item => { const timer = setInterval(() => { if (obj instanceof THING.BaseObject && this.twinSource === 'twinAttribute') { if (item.mLoopType == 'undefind') { if (obj._check(`[${item.mDuration}]`)) { this.runActionFun(item); clearInterval(timer); resolve(true); } } else { if (obj._check(`[${item.mDuration}${item.mLoopType}${item.mDuraData}]`)) { this.runActionFun(item); clearInterval(timer); resolve(true); // return super.nopPromise(); } } } else if (this.twinSource === 'jsonData') { const userdataAttr = `${item.mDuration}`.split('/'); let value; // eslint-disable-next-line no-new-func const JsonStr = typeof this.jsonContent == 'string' ? new Function(`return ${this.jsonContent}`)() : this.jsonContent; // eslint-disable-next-line no-unused-expressions userdataAttr.forEach((t, e) => { // value = value || e ? value[t] : n[t]; if (value || e) { value = value[t]; } else { value = JsonStr[t]; } }); if ((item.mLoopType === 'undefind' && value) || (item.mLoopType === '>' && value > item.mDuraData) || (item.mLoopType === '>=' && value >= item.mDuraData) || (item.mLoopType === '<' && value < item.mDuraData) || (item.mLoopType === '<=' && value <= item.mDuraData) || (item.mLoopType === '==' && value == item.mDuraData) ``` -------------------------------- ### Apply Effects to Objects or Arrays Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This code block applies gradient and opacity lerping effects to either a single THING.BaseObject, an array of objects, or a THING.Selector. It iterates through the provided object(s) and calls `glowlabel` and `lerpOpacityFun` for each. Error handling is included using a try-catch block, and it returns a `nopPromise` upon completion. This function assumes the existence of `obj`, `THING`, `uinv`, and `super.nopPromise()` in its scope. ```javascript try { if (obj instanceof THING.BaseObject) { glowlabel(obj); lerpOpacityFun(obj); } else if (Array.isArray(obj) || obj instanceof THING.Selector) { obj.forEach((item) => { glowlabel(item); lerpOpacityFun(item); }); } } catch (e) { this.consoleError(e); } return super.nopPromise(); ``` -------------------------------- ### Fetch Data from Online URL Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This snippet demonstrates fetching data from a specified online URL using a POST request. It's designed for scenarios where the loop type is '使用接口数据' (Use API Data). ```javascript if (this.onlineurl && this.mLoopType == '使用接口数据') { this.online = async function(obj){ const res = await fetch(this.onlineurl, { method: 'post', ``` -------------------------------- ### Show and Hide Digital Twin Objects using JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Manages the visibility of digital twin objects in the 3D scene. It supports showing, hiding, and controlling inheritance of visibility settings. Dependencies: sm_action_object_visible, sm_action_object_invisible, sm_action_object_inheritvisible. Inputs: THING.App.current.query results. Outputs: Updates object visible state. ```javascript // Initialize visibility plugins const showAction = new sm_action_object_visible(); const hideAction = new sm_action_object_invisible(); // Show objects showAction.mVisible = true; const pipes = THING.App.current.query('.pipe'); showAction.update(pipes); // Hide objects hideAction.mVisible = false; const cables = THING.App.current.query('.cable'); hideAction.update(cables); // Configure visibility inheritance const inheritVisAction = new sm_action_object_inheritvisible(); inheritVisAction.mVisible = true; // Inherit parent visibility const components = THING.App.current.query('#assembly_01 .component'); inheritVisAction.update(components); // Conditional visibility const structure = THING.App.current.query('#structure_01')[0]; showAction.mVisible = true; showAction.update(structure); console.log('Structure visible:', structure.visible); setTimeout(() => { hideAction.update(structure); console.log('Structure visible after hide:', structure.visible); }, 2000); // Output: Structure visible: true // Output (after 2s): Structure visible after hide: false ``` -------------------------------- ### Configure Object Pickability using JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Controls whether digital twin objects can be selected in the 3D scene. It allows enabling or disabling pickability for individual objects or groups, with options for inheriting parent object settings. Dependencies: sm_action_object_pickable, sm_action_object_inheritpickable. Inputs: THING.App.current.query results. Outputs: Updates object pickable state. ```javascript // Initialize pickability plugin const pickableAction = new sm_action_object_pickable(); // Disable picking for an object pickableAction.mPickable = false; const background = THING.App.current.query('#background_mesh')[0]; pickableAction.update(background); // Enable picking for interactive elements pickableAction.mPickable = true; const buttons = THING.App.current.query('.ui-button'); pickableAction.update(buttons); // Configure pickability inheritance const inheritPickAction = new sm_action_object_inheritpickable(); inheritPickAction.mPickable = false; // Don't inherit parent's setting const overlay = THING.App.current.query('#info_overlay')[0]; inheritPickAction.update(overlay); console.log('Background pickable:', background.pickable); console.log('Overlay inherit pickable:', overlay.inheritPickable); // Output: Background pickable: false // Output: Overlay inherit pickable: false ``` -------------------------------- ### JavaScript UI Configuration Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md Defines the UI configuration for a component, specifically for a text input labeled '标签' (label) with a default value of '默认' (default). This input is intended for a unique identifier for commands and can be customized by the user. ```javascript get ui() { return [{ name: 'mStr', type: 'text', label: '标签', default: '默认', description: '执行当前命令的唯一标识,可自定义。', value: this.mStr, }]; } ``` -------------------------------- ### JavaScript: Fullscreen Display and UI Element Management Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This code manages the fullscreen display of an element and its associated iframe. It sets element dimensions to fill the screen and creates auxiliary DOM elements ('domTop', 'domMain', 'domMainBtn') for custom UI interactions, such as tooltips and a close button. Dependencies include standard browser DOM APIs. ```javascript } else if (this.mValueradio === '全屏显示') { dom.style.height = '100%'; dom.style.width = '100%'; dom.style.top = 0; dom.style.left = 0; domIframe.style.height = '100%'; domIframe.style.width = '100%'; domIframe.style.top = '4px'; const domTop = document.createElement('div'); domTop.setAttribute('id', this.iframeId + 'domTop'); domTop.style.width = '75px'; domTop.style.height = `4px`; domTop.style.position = 'absolute'; domTop.style.top = 0; domTop.style.right = 0; dom.appendChild(domTop); const domMain = document.createElement('div'); domMain.setAttribute('id', this.iframeId + 'domMain'); domMain.style.width = '75px'; domMain.style.height = `75px`; domMain.style.position = 'absolute'; domMain.style.top = 0; domMain.style.right = 0; domMain.style.display = 'none'; dom.appendChild(domMain); if (this.mTopping === '置顶'){ domTop.onmouseover = function (){ domMain.style.display = 'block'; }; domMain.onmouseout = function () { domMain.style.display = 'none'; }; } const domMainBtn = document.createElement('i'); domMainBtn.setAttribute('id', this.iframeId + 'domMainBtn'); domMainBtn.setAttribute('class', 'el-icon-close'); domMainBtn.style.width = `30px`; domMainBtn.style.fontSize = '30px'; domMainBtn.style.fontWeight = 900; domMainBtn.style.color = '#707070'; domMainBtn.style.position = 'absolute'; domMainBtn.style.display = 'line-block'; domMainBtn.style.top = '35px'; domMainBtn.style.right = '35px'; domMain.appendChild(domMainBtn); domMainBtn.onclick = function () { dom.remove(); }; } ``` -------------------------------- ### Select Digital Twin Objects with JavaScript Source: https://context7.com/uinosoft/plugins-resource/llms.txt Marks digital twin objects as selected with custom tags, integrating with the THING.js selection system. Allows for highlighting and interaction management. Requires the 'sm_action_object_select' plugin. ```javascript // Initialize selection plugin const selectAction = new sm_action_object_select(); // Configure selection tag selectAction.mStr = 'inspection'; // Select a single object const equipment = THING.App.current.query('#equipment_03')[0]; selectAction.update(equipment); // The object is now marked as selected console.log('Selection label:', equipment.operationAtomicLabel.twinSelection); // Output: Selection label: [{ key: 'inspection', value: true }] // Select with different tag selectAction.mStr = 'maintenance'; const machine = THING.App.current.query('#machine_05')[0]; selectAction.update(machine); // Check current selection const currentSelection = THING.App.current.selection.list; console.log('Currently selected:', currentSelection.map(obj => obj.name)); // Output: Currently selected: ["machine_05"] ``` -------------------------------- ### Process Input Data for Queries in JavaScript Source: https://gitlab.com/uinosoft/plugins-resource/-/blob/main/操作原子_2025-11-24_155504.md This function processes input data, distinguishing between ThingJS query syntax (like 'businessType=', 'userData/DATA/', '#') and comma-separated names. It uses the 'obj.query' method for ThingJS syntax or splits and queries for comma-separated inputs. It handles single string inputs as well. Dependencies: 'obj.query'. ```javascript inputDataDetail(data, obj) { if (!data) { return; } let temData = data.trim(); // 当孪生体级别爆炸下 按零件筛选(必须是ThingJS语法) 不参与爆炸的零件支持ThingJS语法查询 if (temData.indexOf('businessType=') !== -1 || temData.indexOf('userData/DATA/') !== -1 || temData.indexOf('#') !== -1) { return Array.from(obj.query(temData)); } if (temData && temData.indexOf(',') !== -1) { temData = temData.split(','); } if (obj) { // 孪生体级别爆炸下 不参与爆炸零件根据输入名称查询不参与爆炸得孪生体 let arr = []; if (typeof temData === 'string') { arr = arr.concat(Array.from(obj.query(temData))); } else { temData.forEach(i => { arr = arr.concat(Array.from(obj.query(i))); }); } return arr; } return typeof temData === 'string' ? [temData] : temData; } ```