BBC's guide to development
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • Socket

Socket

A THREE.Group subclass representing a connection point on a Snappable.

It tracks interaction state, manages category-based compatibility, and animates its material colour through a priority-based state machine.

Warning

Meant to be used with ComponentMgr only.

Getting started

const socket = new Socket({ object3d })

// add to scene directly (to avoid, just to illustrate)
scene.add(socket)
  1. Finds the first mesh child → _mesh (snap surface)
  2. Finds any child with userData.type = "up" → _upIndicator
  3. Averages vertex normals of the mesh to compute _normal
  4. Sets _upNormal from the up indicator's position, or defaults to (0, 1, 0)
  5. Parses userData.category / userData.catagory into _categories array (comma-split, trimmed)
  6. Applies a fresh MeshStandardMaterial to the mesh for state-driven colouring

State Machine

Sockets have four independently tracked boolean states:

StateMeaning
isHoveredCursor is over this socket
isClickedMouse button is held down over this socket
isCompatibleCurrent item has a socket that can connect here
isBlockedPlacement at this socket would cause a collision

Additionally, locked is a separate property (not in userData.state) that indicates a snapped connection.

Why is locked separate?

locked is kept separate because it has a fundamentally different lifecycle from the four interaction states.

Interaction states are transient (they are set and cleared every frame by tick() based on the current raycast result. locked is persistent)

It is set once when two blocks snap together and remains set until one of the blocks is removed from the scene.

Mixing it into userData.state would require tick() to explicitly avoid overwriting it on every frame, which would be fragile.

As a standalone property with its own getter/setter, locking and unlocking is self-contained and bidirectional: setting locked = false on one socket automatically clears the partner's reference too.

Colour Priority

When multiple states are active simultaneously, the colour with the highest priority wins:

PriorityStateDefault colourRationale
1locked#ff0000A locked socket is occupied and cannot accept another connection — this is the most important thing to communicate, so it overrides everything else
2blocked#333333Placement would cause a collision; the user should not click even though the cursor is hovering — takes priority over hover and click colours
3isClicked#00ff00Mouse button is held; placement is imminent — more specific than hover, so it wins
4isHovered#0000ffCursor is over this socket — should show clearly but yields to any actionable state above it
5isCompatible#ffff00A block is being previewed that could connect here — background highlight to guide the user, lowest active state
6default#ffffffSocket is visible but no interaction is occurring

1 = Highest, 6 = Lowest

The priority order is fixed in code and is not configurable at runtime.

To change which colour is shown for a given state, use componentMgr.setSocketColors() — but the order in which states override each other cannot be changed without modifying Socket.tick().

API

Constructor

Constructor initialises the new Socket instance

Parameters

  • object3d: The socket group from GLTF (must contain at least one mesh child)
  • debug: If true, adds arrow helpers showing the normal and up direction

Methods

canConnectTo(otherSocket) → boolean

Checks category compatibility between this socket and otherSocket using OR logic.

Parameters
  • otherSocket: The socket to check for compatibility
Returns
  • true if either socket has an empty category list (wildcard)
  • true if any category string is shared between both sockets
  • false if both have non-empty category lists with no overlap

setState(type, value) → this

Sets a state flag and dispatches the corresponding event if the value changed.

Parameters
  • type: Sets the state of the socket, one of 'isHovered', 'isClicked', 'isCompatible', 'isBlocked'
  • value: Sets the value of the state flag, true or false

getState(type?) → boolean | object

Returns the value of a single state flag, or the full state object if type is omitted.

Parameters
  • type: Gets the state of the socket, one of 'isHovered', 'isClicked', 'isCompatible', 'isBlocked'
Returns
  • boolean: The value of the state flag
  • object: The full state object

tick()

Lerps the socket mesh material colour toward the target colour determined by state priority (see Colour Priority below).

Also lerps opacity. Called automatically by Snappable.tick().

zFightFix(cameraPosition?)

Nudges the socket mesh along its normal by a distance proportional to camera distance, preventing z-fighting with the block surface.

Parameters
  • cameraPosition: The position of the camera

clone(recursive?) → Socket

Clones the original socket group and creates a new Socket from it.

Parameters
  • recursive: Whether to clone the object recursively

dispose()

Removes arrow helpers, disposes the mesh geometry and material.

Properties

normal

Socket forward direction (from averaged vertex normals), read-only

upNormal

Up reference direction (from up indicator position or (0,1,0)), read-only

categories

Parsed category strings, read-only

mesh

The socket's snap surface mesh, read-only

locked

get/set — when set to false, also unlocks the lockedPartner and clears both references

lockedPartner

get/set — setting a partner automatically locks this socket; clearing it unlocks both

debug

get/set — toggles arrow helpers for normal and up direction

Static property

Socket.updateColors(colors)

Updates the shared static colour configuration for all socket instances. Takes effect immediately on the next tick().

Parameters
  • colors: An object with the following properties:
    • default: The default colour of the socket
    • hovered: The colour of the socket when hovered
    • clicked: The colour of the socket when clicked
    • compatible: The colour of the socket when compatible
    • locked: The colour of the socket when locked
    • blocked: The colour of the socket when blocked

Call via componentMgr.setSocketColors(colors) to use the public API.

Events

Events are dispatched via THREE.EventDispatcher when state changes:

isHovered

Hover state change

Parameters
  • socket: The socket that is hovered
  • name: The name of the socket
  • value: The value of the state flag

isClicked

Click state change

Parameters
  • socket: The socket that is clicked
  • name: The name of the socket
  • value: The value of the state flag

isCompatible

Compatible state change

Parameters
  • socket: The socket that is compatible
  • name: The name of the socket
  • value: The value of the state flag

isBlocked

Blocked state change

Parameters
  • socket: The socket that is blocked
  • name: The name of the socket
  • value: The value of the state flag

locked

Lock state change

Parameters
  • socket: The socket that is locked
  • name: The name of the socket
  • value: The value of the state flag
Edit this page
Last Updated: 4/27/26, 12:56 PM
Contributors: Nicolas Jaenen