npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

architwin

v1.18.10

Published

ArchiTwin Library for Matterport

Readme

ArchiTwin Library

Table of Contents


Installation

Install Using NPM

To install the latest ArchiTwin package:

npm i architwin

Getting Started

Prerequisites

Before you start coding your architwin powered app, there are a few things you need to have ready to ensure that you are able to run the app properly without interruptions. For a seamless development experience, make sure to have the following ready:

  • appKey: your appKey is used to authenticate your connection to Matterport when loading the 3D space. For security purposes, the appKey can only be used by a domain (e.g. awesomesite.com) it is associated with. This key is important especially when you launch your app in production and utilize your own site domain. Go to your Matterport dashboard to get your app key and make sure to whitelist your app domain that you will use this key with.
  • Matterport Bundle SDK: You must have a copy of Matterport's Bundle SDK and serve it under your applications public directory or the equivalent directory your chosen framework recommends you to place public assets. As of the time of this writing, the library has been tested to work with version 25.10.1 of the bundle SDK. We recommend using this version for your app or use the latest version of the bundle SDK. You can get the latest version of the bundle SDK from matterport by clicking here

Define an iFrame as target for the Showcase

This example uses Vue's ref attribute to reference the target iFrame. Please consult the official documentation of your preferred framework of choice on how to reference a target component.

<template>
  <div class="at_showcase_container" id="showcase-container">
    <iframe id="mp-showcase" class="showcase" scrolling="no" width="100%" height="700" frameborder="0" allow="xr-spatial-tracking" allowfullscreen></iframe>
    <div class="at_map_container">
      <div id="at-map">
      </div>
    </div>
  </div>
</template>

Import the library

<script lang="ts">
import * as atwin from 'architwin';
//We also support default imports using import * as atwin from 'architwin';
import type { IMPConfig, IUser } from 'architwin/lib/types'; //for typescript projects
import { onMounted, ref } from 'vue';

const mpIframe = ref<HTMLIFrameElement>()

....
</script>

Setup your proxy

This section may not apply to you depending on your setup and use case. You may proceed to the next section if so.

In your vite.config.ts, add the following block of code. This will allow your app in your development environment to send API request to our servers and circumvent CORS issues. If you are not using vite as your build tool, please refer on the official documentation of your build tool of choice on how to setup the proxy.

You may have to change the VITE_PROXY value if you intend to direct your api requests on another server during development.

During production deployment you may need to setup proxy settings using your web or proxy server (ie: nginx, apache).

import { fileURLToPath, URL } from "node:url";

import { defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue"; //for Vue projects
import { svelte } from '@sveltejs/vite-plugin-svelte' //for Svelte projects
import react from '@vitejs/plugin-react' //for React projects
import dotenv from "dotenv";

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd(), "");
  console.log("=== env ===", mode, JSON.stringify(env));

  const VITE_PROXY = "https://basic-dev.rev-kitten.com";

  return {
    env: env,
    plugins: [
      vue(), //for vue projects,
      svelte(), //for svelte projects,
      react(), //for react projects
      ],
    server: {
      host: true,
      port: 5173,
      proxy: {
        "/api": {
          target: VITE_PROXY,
          secure: false,
          changeOrigin: true,
        },
        "/admin": { target: VITE_PROXY, secure: false, changeOrigin: true },
        "/default": { target: VITE_PROXY, secure: false, changeOrigin: true },


      },
    },
    devServer: {
      host: true,
      port: 5173,
      proxy: {
        "/api": { target: VITE_PROXY, secure: false, changeOrigin: true},
        "/admin": { target: VITE_PROXY, secure: false, 
          changeOrigin: true },
        "/default": { target: VITE_PROXY, true: false, changeOrigin: true },
      },
    },
    
    resolve: {
      alias: {
        "@": fileURLToPath(new URL("./src", import.meta.url)),
      },
    },
    //@ts-ignore
    test: {
      globals: true,
      environment: "jsdom",
    }
  };
});

Connect to a Space

In order to connect to a space, you may use connectSpace() method.

<script lang="ts">

  onMounted( async() => {

  //matterport url 
  const spaceUrl = "https://my.matterport.com/show/?m=<space-id>";

  const config: IMPConfig = {
    iframeId: 'mp-showcase',
    bundlePath: "path/to/bundle/",
    appKey: 'YOUR-APP-KEY'
    play: 1,
  }

  // more config options as explained later
  await atwin.connectSpace(spaceUrl, null, config)

})

</script>

Once connected, the interactive Space will be rendered in the target iFrame. A Space generally contains Tags, 3D objects, and Sweeps, and via the custom loaders the library provides, may also render videos, slideshows, etc.

You can navigate the Space using a keyboard and mouse, or programmatically using the methods defined in this library.

Executing methods on specific App Phases

WARNING: This feature is deprecated, subscribe using Space Events instead

Your application may need to execute certain methods during the initialization of your 3D space. For example, you may want to useaddObjectToSpace() method to render a model to your 3D space the moment the 3D space becomes interactive. While you can always just invoke the function after the connectSpace() method there may be times where this will cause an error as the connectSpace() method which is an async method, may have not finished initializing the necessary internal variables that allow other methods to work properly. When you invoke the connectSpace() method, the library does some internal validation and then goes to several phases to render your 3D space and make it interactive. These phases are the following:

ARCHTWIN APP PHASES

  • LOADING: Initial fetch request to matterport. This is where the bundle downloads the 3D space from matterport and starts rendering it
  • STARTING: Matterport begins the transition to the start location
  • PLAYING The 3D space is now ready for user interaction

You can also view the technical diagram of how this works below:

To invoke a function from your application during one of the phases, simply pass the function name as a parameter in the connectSpace() method. Make sure to not add a parenthesis to your function name when you pass it as a parameter to avoid invoking the function prematurely.

Example:

//Your application side function
async function runThisOnPlayState(){
const tags = await axios.get('my-custom-endpoint')

//Keep in mind that you should map the data from your endpoint into an object structure that the library supports

await atwin.showTags(tags)
}

await atwin.connectSpace(spaceUrl, auth, config,{onPlay:runThisOnPlayState})

In this example, the method named runThisOnPlayState is passed as a value to the onPlay key of an object. This will invoke the function during the PLAYING phase of the library. To invoke your function in a different phase, simply pass it to a different key in the object. You can pass your functions to onLoad,onStart, and onPlay. Async and synchronous functions are valid. Refer to the table below for more information

| parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | onLoad | Function | no | none | async or non-async function| | onStart | Function | no | none | async or non-async function| | onPlay | Function | no | none | async or non-async function|

Space Overview

Space - Space is an immersive and realistic Digital Twin model of a physical space, with virtual custom objects like animated 3D objects, Video Screens, Slideshow Screens and Tags, co-existing and enhancing the real objects.

A user should be able to navigate around using PC or devices (keyboard and mouse), measure real object dimensions and interact with the virtual objects as if you are actually visiting the physical space.

Sweeps - Spaces have static sweep markers (white circles on the floor) which serve as primary navigation points. Users can go to sweeps (or click), stand, and look around.

Tags - Spaces also have tags, which are virtual markers attached to objects or locations in the space. Tags can be clicked to render and display relevant content such as web pages, videos, images, or text descriptions. It is possible to go directly to any specific tag (gotoTag) from anywhere in the Space.

They can be used as a quick way to navigate around the space.

3D Objects - Spaces usually contain 3D objects or three-dimensional models. Some 3D objects may have simple animations.

Video Screens - Another interesting type of object that can be found inside the space is Video Screens. They practically look like TV screens placed at selected locations. Video screens automatically play when a user is nearby (within 2 meters) and automatically turn off when the user moves away.

Slideshow Screens - Space can also contain Image Slideshow Screens. This is similar to the Video Screen, but uses static images. Clicking on the right section of the current slide image will display the next slide. Clicking on the left section will display the previous slide.

The slideshow can be auto played in whole by clicking the lower-right corner.

Note: We use the word Space and Showcase interchangeably.

Subscribing to Space Events

Your 3D space allows your users to move around and interact with objects loaded into that space. Interactions such as clicking and dragging 3D objects in a space are events that your app may need to listen to and subsequently trigger the appropriate function for such an event.

You can subscribe to a particular event and pass callback method or methods to trigger when a subscribed event is fired using the subscribeSpaceEvent() method.

The method accepts the following as its parameters: | parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | eventType | SPACE_EVENTS or string | yes | none | valid event type | | callback | Function or Array of Functions | yes | none | function or async function |

Subscribing a method to an event

To subscribe to an event, simply call the subscribeSpaceEvent() and pass the event you want to subscribe to and the method you want to trigger. Subscribing to an event will also return to you the data of an object if you are interacting with one. Said object data will implement the IShowcaseObject interface.

Example:

function myFunction(objectData){
  console.log("I will run during a DRAG_END event",objectData)
}

atwin.subscribeSpaceEvent('DRAG_END',myFunction)

You can subscribe your method to more than one event. Currently, we support subscribing only the following events but we are working to add more events in the future.

SUPPORTED EVENTS

  • CLICK
  • HOVER
  • DRAG
  • DRAG_BEGIN
  • DRAG_END
  • LOADING_PHASE
  • STARTING_PHASE
  • PLAYING_PHASE
  • PLACED_TAG
  • TAG_SAVED
  • TAG_DISPOSED
  • MEDIASCREEN_EXPANDED
  • MEDIASCREEN_MINIMIZED
  • MEDIA_PLAY
  • MEDIA_PAUSE
  • MEDIA_MUTE
  • MEDIA_UNMUTE
  • MEDIA_ENDED
  • CURRENT_USER_LOADED
  • CURRENT_USER_CHANGED
  • PARTICIPANT_CHANGED
  • PARTICIPANT_ADDED
  • PARTICIPANT_REMOVED
  • PARTICIPANT_VIDEO_ON
  • PARTICIPANT_VIDEO_OFF
  • PARTICIPANT_AUDIO_STATE
  • MEETING_ENDED
  • MEETING_CLOSED
  • SELECTED_TAG
  • MODEL_RENDERED
  • MODEL_DISPOSED
  • TAG_MESSAGE_OPENED
  • TAG_MESSAGE_SENT
  • TAG_MESSAGE_RETRIEVED
  • TAG_RECEPIENT_CHANGED
  • TAG_LINK_COPIED
  • TAG_LINK_GENERATED
  • SET_TAG_ICON
  • VIEW_TAG_MESSAGE
  • TOOLBAR_LOADED
  • SWEEP_COLLECTION_UPDATED
  • MINIMAP_SWEEP_CLICK
  • MINIMAP_SWEEPS_RENDERED
  • SCREENSHOT_CAPTURED
  • ON_MOVE_SWEEP
  • ON_CAMERA_MOVE
  • USER_VIEW_POINT
  • TAGPLACER_CREATED
  • ROOM_CHANGED
  • ARRIVED_ON_SWEEP
  • CAMERA_ROTATE_START
  • CAMERA_ROTATE_END
  • CURRENT_CAMERA_POSE
  • CURRENT_CAMERA_ZOOM

For more information regarding the loading,starting, and playing phase events. Please refer to this section

Subscribing multiple methods to an event

If you wish to subscribe multiple methods to an event, you can use the following methods listed below.

Method 1: Subscribing each method one at a time

function myFunction(objectData){
  console.log("Function 1")
}

function myFunction2(objectData){
  console.log("Function 2")
}

atwin.subscribeSpaceEvent('DRAG_END',myFunction)
atwin.subscribeSpaceEvent('DRAG_END',myFunction2)

Method 2: Placing multiple methods in a parent method and passing it to the subscribeSpaceEvent method

function myFunction(){
  console.log("Function 1")
}

function myFunction2(){
  console.log("Function 2")
}

function parentFunction(objectData) {
  myFunction()
  myFunction2()
}

atwin.subscribeSpaceEvent('DRAG_END',parentFunction)

Method 3: Inserting multiple methods into an array and passing it to the subscribeSpaceEvent method.

function myFunction(){
  console.log("Function 1")
}

function myFunction2(){
  console.log("Function 2")
}

const functionArray = [myFunction,myFunction2]

atwin.subscribeSpaceEvent('DRAG_END',functionArray)

Keep in mind that the library's event system utilizes a FIFO algorithm. Your functions will always be executed in chronological order, meaning functions that were subscribed first will be executed first.

Unsubscribing a method from an event

If you wish to unsubscribe your method from a subscribed event, simply call the unsubscribeSpaceEvent() method to do so. The method accepts the following parameters:

The method accepts the following as its parameters: | parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | eventType | SPACE_EVENTS or string | yes | none | valid event type | | callback | Function or Array of Functions | yes | none | function or async function |

Example:

function myFunction(){
  console.log("I will be unsubscribed and no longer trigger during the next DRAG_END event")
}

atwin.unsubscribeSpaceEvent('DRAG_END',myFunction)

If you used Method 3 in subscribing multiple methods. You can pass the same array to the unsubscribeSpaceEvent() method and they will all be unsubscribed from the event.

const functionArray = [myFunction,myFunction2]

atwin.unsubscribeSpaceEvent('DRAG_END',functionArray)

Creating Custom Events

The library has a list of default event types you can subscribe to but you may at times need to create your own event type to use for a specific task. You can easily create and subscribe to your own custom event by using registerCustomSpaceEvent() and subscribeSpaceEvent() respectively. Here is how to do it.

IMPORTANT: Your custom event type name must not be the same as an existing custom event type or a default event type. Doing so will return an error and the registration will fail.

STEP 1: Register your event type name. As a convention, the name of your event type should be in uppercase and use snake_case (e.g. FOO_BAR). It is important to register your custom event type first before subscribing a method to it. You can register one or multiple events using the method.

//Register one custom event type
atwin.registerCustomSpaceEvent('MY_EVENT')

//Register multiple custom events
const newEvents = ['FOO','BAR','MY_EVENT']
atwin.registerCustomSpaceEvent(newEvents)

STEP 2: Subscribe to your custom event

function myFunction(objectData){
  console.log("Function 1")
}

atwin.subscribeSpaceEvent('MY_EVENT',myFunction)

To trigger your custom event, you can use the dispatchSpaceEvent() in your app. You can also optionally pass a data payload with said event. Just make sure that you have done steps 1 and 2 before doing so.

The dispatchSpaceEvent() method accepts the following as its parameters: | parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | eventType | SPACE_EVENTS or string | yes | none | valid event type | | payload | any | no | none | any |

const someData = {
  //some data here
}

atwin.dispatchSpaceEvent('MY_EVENT',someData)

Points of Interest

Tags are primarily used to mark locations or objects in space for quick and direct navigation. Tags usually contain additional content that will be rendered when hovered. Contents can be web pages, text descriptions, videos, or images.

You may use the getTags() method in order to get a list of Tags found in the space.

You may use the goToTag() method in order to navigate to a specific Tag

You may use the getSweeps() method in order to get a list of Sweeps found in the Space.

You may use the moveToSweep() method in order to move to a specific Sweep

| parameter | type | required | default | values | | :----: | :----: | :---: | :---: | :---: | | sweepId | string | yes | | Id of the sweep |

import * as atwin from 'architwin';

...

const spaceUrl = "https://my.matterport.com/space/m?=<space-id>"

const ispace = {
  id: 1;
  name: "mySpace";
  space_url: spaceUrl;
  tagpin_image: null;
} as ISpace

const tagId = "5"
const sweepId = "10"

// returns a list of Tags found in the Space
await atwin.getTags(ispace)

// to navigate to specific Tag and accepts a Tag's ID
await atwin.goToTag(tagId)

// returns a list of Sweeps found in the Space
await atwin.getSweeps()

// to move to a specific Sweep
await atwin.moveToSweep(sweepId)

...

More Examples:

import * as atwin from 'architwin';

...

// get current sweep data
await atwin.getCurrentSweep()

...

Adding, removing and customizing Tags

Tags are interactive elements that can be added to a 3D Space. Tags are essentially clickable annotations or markers that can be placed within the 3D model of a space, typically linking to additional information or media. They enhance the user experience by providing context and additional details about specific features or objects within the Space.

To render a tag in the Space, you can use renderTag() method. The renderTag() method accepts payload input.

Example:

import * as atwin from 'architwin'

const payload = {
  tag: { /* Define your tag descriptor here */ },
  relocate: true,
  attachments: ['attachment1.png', 'attachment2.png'],
  icon: 'icon.png'
};

try {
  const renderedTag = await atwin.renderTag(payload);
  console.log('Rendered Tag:', renderedTag);
} catch (error) {
  console.error('Error rendering tag:', error);
}

You can define your tag descriptor like this:

const tag = {
  id?: string;
  anchorPosition: Vector3;
  stemVector: Vector3;
  stemVisible?: boolean;
  label?: string;
  description?: string;
  color?: Color;
  opacity?: number;
  iconId?: string;
  attachments?: string[];
};

To remove a tag in the Space, you can use disposeTags(). The disposeTags() has no parameter.

Example:

import * as atwin from 'architwin'

// Example usage of the disposeTags function
async function removeTagsFromSpace() {
  try {
    console.log("Removing Mattertags from space...");
    await atwin.disposeTags();
    console.log("Mattertags removed successfully.");
  } catch (error) {
    console.error("Error removing Mattertags:", error);
  }
}

// Call the function to remove Mattertags from the space
removeTagsFromSpace();

Removing a specific tag in the Space, the disposeTag is the right method to use.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
};

try {
  await atwin.disposeTag(payload);
  console.log('Tag disposed successfully.');
} catch (error) {
  console.error('Error disposing the tag:', error);
}

Tags are customizable. You can customize the tag label, description, stem, icon, and color.

editTagLabel() is the right method to change or edit the label of a specific tag.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  label: 'New Label' // Specify the new label for the tag
};

try {
  await atwin.editTagLabel(payload);
  console.log('Tag label edited successfully.');
} catch (error) {
  console.error('Error editing the tag label:', error);
}

To edit or change the description of a tag, use the editTagDescription() method.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  description: 'New Description' // Specify the new description for the tag
};

try {
  await atwin.editTagDescription(payload);
  console.log('Tag description edited successfully.');
} catch (error) {
  console.error('Error editing the tag description:', error);
}

You can also choose to show or hide the tag stem by invoking editTagStem().

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  stemVisible: true // Specify the new stem visibility value
};

try {
  await atwin.editTagStem(payload);
  console.log('Tag stem visibility edited successfully.');
} catch (error) {
  console.error('Error editing the tag stem visibility:', error);
}

The tag icon is also editable; use the editTagIcon() method for this.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  icon: 'new-icon.png', // Specify the new icon file path or reference (optional)
  color: 'blue' // Specify the new color for the tag
};

try {
  await atwin.editTagIcon(payload);
  console.log('Tag icon and color edited successfully.');
} catch (error) {
  console.error('Error editing the tag icon and color:', error);
}

You can also change the color of the tag itself, just use the editTagColor() method.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  color: { r: 255, g: 0, b: 0 } // Specify the new color (RGB format)
};

try {
  await atwin.editTagColor(payload);
  console.log('Tag color edited successfully.');
} catch (error) {
  console.error('Error editing the tag color:', error);
}

Attaching media to a tag is also possible; use the attachTagMedia() method.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  attachments: ['media1.jpg', 'media2.jpg'] // Specify the media file paths
};

try {
  await atwin.attachTagMedia(payload);
  console.log('Media attached to the tag successfully.');
} catch (error) {
  console.error('Error attaching media to the tag:', error);
}

You can also remove the attached media, just call the detachTagMedia() method.

Example:

import * as atwin from 'architwin'

const payload = {
  tagId: '123456789', // Replace with the actual tag ID
  attachmentIds: ['attachment1', 'attachment2'] // Specify the attachment IDs to detach
};

try {
  await atwin.detachTagMedia(payload);
  console.log('Media detached from the tag successfully.');
} catch (error) {
  console.error('Error detaching media from the tag:', error);
}

Please explore the Tags related function to learn more what you can do with tags.

Accessing List of Rendered Objects and Object Structure

Objects that have been loaded and rendered into the 3D space are stored in an array called _3DXObjects which you can access by calling it this way

atwin._3DXObjects

All the elements in this array implement the IObjectData interface. Each element in the array contains all the data you would need to manipulate the object.

interface used (TS)

interface IObjectData {
  collider?: any
  object: IShowcaseObject
  component: Scene.IComponent
  node: Scene.INode
  type?: string
}

Each object element inside atwin._3DXObjects contains the value keys:

collider - Collider components define the shape of a 3D/2D object for the purposes of physical collisions. A collider, which is invisible, does not need to be the exact same shape as the GameObject’s mesh.

object - The object key is an object that implements the IShowcaseObject interface. This is one of the most important values as the object contains all the information about an object such as its id,name,position,rotation,scale,amazon_uri link, and etc. You can look at the interface below to view the full makeup of the object key.

interface used (TS)

export interface IShowcaseObject {
  id: number;
  showcase_id: number;
  object_id: number;
  user_id: number;
  object_position: {
    x: number;
    y: number;
    z: number;
  };
  object_rotation: {
    x: number;
    y: number;
    z: number;
  };
  object_scale: {
    x: number;
    y: number;
    z: number;
  };
  autoplay: boolean;
  autoplay_distance: number;
  offset_position: number;
  offset_rotation: number;
  position_unit: string;
  showcase_object_name: string;
  is_deleted: boolean;
  is_read: boolean;
  is_new: boolean;
  object_data: I3DObject;
}

component: This object contains functions and variables responsible for initializing, updating, and destroying a rendered object's mesh, texture, etc. This object also contains the three.js instance. Since the 3D space is rendered with Three.js under the hood. You can use this instance to invoke methods made available by three.js. This gives you a lot of flexibility and control provided you know how to use it. This documentation will not cover Three.js specific methods. Visit their official website if you want to learn more about it.

node: The node is responsible for managing the lifecycle of a 3D/2D object. The node can be used to start() and stop() a rendered model. Invoking start() will render the model into the scene while stop() will destroy it and remove it from the scene.

type: A string that states the file or object type of a 3D/2D object. The file type could be any of the following

Valid Types

| type | context | description | | :----: | :----: | :---: | | GLB | 3D model | A 3D model with or without animation | | FBX | 3D model | A 3D model with or without animation | | FRAME | Media Screen | A customizable media screen | | ZIP | slideshow | A zip file rendered as a image slideshow |

The atwin.selectedObject variable is an example of a variable that implements this interface and contains this data.

Transforming Objects

Transformation such as translate, scale, and rotate are actions used to manipulate objects in a 3D space. These transformations allow you to change an object's position, size, and orientation respectively.

NOTE: Please be aware that transform controls are disabled when viewMode in the config object you pass into connectSpace is undefined or is set to public. To enable transform controls in your 3D space. Make sure to set viewMode to 'interactive'.

Translate - Translation refers to moving an object from one position to another in space. It involves shifting the object's entire coordinate system without altering its orientation.

Scale - Scaling is the process of changing the size of an object by uniformly increasing or decreasing its dimensions along each axis. It can make an object larger (scaling up) or smaller (scaling down).

Rotate - Rotation involves changing the orientation or angle of an object around a specified point or axis. It rotates the object clockwise or counterclockwise by a certain angle.

There are several methods that allows you to transform an object. Let's go through each one

Transforming Object by clicking it

Clicking on any object in the space will attach the axis controls to it. By default, clicking on an object will show axis controls for translating the object. You can then use your mouse cursor to click and drag the object to modify its position, rotation, and scale in whatever way you prefer. See screenshot for reference

You can switch the transform mode on the currently selected object by using the setTransformMode() method.

Please take note that transform controls can only be attached to one object at a time. Clicking on another object will remove the transform controls from the previous object and add them to the currently selected object. It is impractical to attach multiple transform controls on more than one object. If you wish to programmatically transform multiple objects, the next method offers a solution.

If you wish to access the object data of the object that has been clicked on, You can do so by calling the atwin.selectedObject variable which returns an object implementing the IObjectData interface containing all the necessary data you need. Know more about the structure of an object by going to this section

import * as atwin from 'architwin';

...

console.log("Selected