Working with Three.js: Utilizing the SpotLight and dat.gui

I have implemented a SpotLight in my scene along with an OctahedronGeometry as a visual aid for the user. The SpotLight can be moved using transformControls by selecting it, which is working properly.

However, the issue arises when I try to edit the settings of the SpotLight while it is selected. Currently, I end up interacting with the geometry rather than directly manipulating the SpotLight itself.

Below is the function I am using:

var aSpotLight = document.getElementById("addSpotLight");
aSpotLight.addEventListener("click", addSpotLight, false);

    function addSpotLight(){
        var object = new THREE.SpotLight( 0xffffff, 1, 0, Math.PI * 0.1, 10 );
        object.name = 'SpotLight';
        var helper = new THREE.Mesh(new THREE.OctahedronGeometry(10, 0), new THREE.MeshBasicMaterial( { color: 0x00ee00, wireframe: true, transparent: true } ));
        helper.position.set( 0, 30, 0 );
        object.position.set( 0, 30, 0 );

        scene.add(helper);
        helper.add( object );

        objects.push(object);

        renderer.render( scene, camera );
        material.needsUpdate = true;
    }

Additionally, here are the dat.gui settings I have in place:

selectedObjectAppearance = {
        lightColor : 0xffffff,
        lightDistance : 10,
        lightIntensity : 1,
        lightlightShadowDarkness : 1
    };

    guiObject.addColor(selectedObjectAppearance, 'lightColor').name('Light Color').onChange(function (e) {SELECTED.children.color = new THREE.Color(e);});
        guiObject.add( selectedObjectAppearance, 'lightDistance' ).min(1).max(15).step(0.5).name('Light distance').onChange(function (e) {SELECTED.distance = e;});
        guiObject.add( selectedObjectAppearance, 'lightIntensity' ).min(0).max(1).step(0.05).name('Light intensity').onChange(function (e) {SELECTED.intensity = e;});
        guiObject.add( selectedObjectAppearance, 'lightlightShadowDarkness' ).min(0).max(1).step(0.05).name('Light shadow darkness').onChange(function (e) {SELECTED.shadowDarkness = e;});

[EDIT] Lastly, here's the SELECTED variable being used:

function onDocumentMouseDown(event){
    event.preventDefault();
    if($(event.target).is('canvas')){
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(objects);
        if(intersects.length > 0){
            SELECTED = intersects[ 0 ].object;

            control.attach(SELECTED);
            scene.add(control);
            $(guiObject.domElement).attr("hidden", false);
        } else{
            control.detach(SELECTED);
            scene.remove(control);
            control.update();
            $(guiObject.domElement).attr("hidden", true);
        }
    } else{
        $(guiObject.domElement).attr("hidden", false);
    }
}

Any suggestions on how I can address this issue and ensure direct editing of the SpotLight settings?

Answer №1

There are two possible approaches to take, and your decision should be based on the outcome you desire.

The first approach involves inserting the helper as a sub-element of your object. This way, when you interact with the helper, you can also modify the properties of its parent.

Alternatively, the second approach suggests assigning a unique name to the helper (e.g. helper.name = SpotLightHelper) and then employing the following method:

scene.traverse( function( child ) {
    if (child.name === 'SpotLightHelper') {
        // perform actions specific to this scenario
    }
    else if (child.name === 'PointLightHelper') {
        // execute tasks tailored to this condition
    }
} );

Answer №2

guiObject.addColor(selectedObjectAppearance, 'lightColor').name('Light Color').onChange(function (e) {
    scene.traverse( function( child ) {
        var obj = helper.children[0];

        if ((SELECTED === helper) && (child instanceof THREE.SpotLight)) {
            obj.color = new THREE.Color(e);
        }
        else if ((SELECTED === helper) && (child instanceof THREE.PointLight)) {
            obj.color = new THREE.Color(e);
        }
        else if ((SELECTED === helper) && (child instanceof THREE.DirectionalLight)) {
            obj.color = new THREE.Color(e);
        }
    } );
});

Worked like a charm.

Answer №3

Recently, I encountered an issue while working on my project.

guiObject.addColor(selectedObjectAppearance, 'lightColor').name('Light Color').onChange(function (e) {
    scene.traverse( function( child ) {

        if (SELECTED.name === 'SpotLightHelper') {
            var object = scene.getObjectByName("SpotLight");
            object.color = new THREE.Color(e);
        }
        else if (SELECTED.name === 'PointLightHelper') {
            var object = scene.getObjectByName("PointLight");
            object.color = new THREE.Color(e);
        }
        else if (SELECTED.name === 'DirectionalLightHelper') {
            var object = scene.getObjectByName("DirectionalLight");
            object.color = new THREE.Color(e);
        }
    } );
});

However, the issue lies in the fact that this code only seems to work for the first instance of SpotLight/PointLight/DirectionalLight in my scene.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to use Jquery ScrollTo() to navigate to an element on a page using a class selector

Building on the information from this source, I have a question: How can I resolve the same issue using a class selector like $('.class')? I am encountering an error message that says Uncaught TypeError: undefined is not a function This occurs ...

Text area featuring unique border design, with border color change upon focus?

Currently, I have a text area with borders that are designed in a unique way. However, I am looking to change the border color when the user focuses on the text area. Do you have any suggestions on how I can achieve this effect without affecting the curre ...

Tips for transferring HTML code to a controller

Currently facing an issue while working with MVC and attempting to store HTML code from a view in a database field. In the JS section of my MVC solution, I have the following code snippet: var data = { id_perizia: $("#id_perizia").val(), pinSessione: $("# ...

The sidebar is not correctly displaying at full height

Having trouble getting the sidebar to fit perfectly between the header/nav and footer in full height. <html> <head> <meta charset="utf-8"> </head> <body> <header> <div class="header"> & ...

Implementing a delay of X seconds after a click event in JQuery: A step-by-step guide

Is there a way to delay the triggering of a click event after one has been recently triggered? I am facing an issue on my website where users can click multiple times on the "dropdown icon" and cause it to toggle the slide effect multiple times. What I wan ...

The function 'downloadFunc' is not recognized as a valid function within the context of ReactJS custom hooks

Here is a unique custom hook that triggers when the user presses a button, calling an endpoint to download files as a .zip: import { useQuery } from 'react-query'; import { basePath } from '../../config/basePath'; async function downlo ...

What could be causing the jQuery change function to stop working after loading HTML with AJAX?

When loading a form, I use AJAX to dynamically populate a select element from a PHP file. Previously, my change function was working fine (it displayed another input when 'other' was selected). However, after implementing the dynamic AJAX populat ...

Showing events from MySQL database on Vue.js Fullcalendar

I am trying to fetch events from my MySQL database and pass them to my Vue component to be displayed on the FullCalendar. However, the event array is being populated with a full HTML document. Below is my EventController: public function getEvents() { ...

Utilizing a Dependency Injection container effectively

I am venturing into the world of creating a Node.js backend for the first time after previously working with ASP.NET Core. I am interested in utilizing a DI Container and incorporating controllers into my project. In ASP.NET Core, a new instance of the c ...

An issue with the AngularJS [$parse:syntax] error has been identified when using specific data in the

I encountered an issue when attempting to create an AngularJS ui-grid table with data that includes a '(' and then whitespace before the closing ')' within a string. This resulted in an AngularJS error message: Syntax Error: Token &a ...

"Efficient Implementation: Expo React Native Utilizes Custom Font Loading One Time Only

Hello everyone, I'm a newcomer here and I'm currently using Expo to build a react native app. My goal is to implement custom fonts in my project. I've gone through the documentation which can be found here. However, I'm facing an issue ...

Error encountered on NodeJS server

Today marks my third day of delving into the world of Angular. I've come across a section that covers making ajax calls, but I've hit a roadblock where a tutorial instructed me to run server.js. I have successfully installed both nodejs and expre ...

Is Fetch executed before or after setState is executed?

I've encountered an issue while trying to send data from the frontend (using React) to the backend (Express) via an HTML form, and subsequently clearing the fields after submission. The code snippet below illustrates what I'm facing. In this scen ...

Designing a sequential bar graph to visualize intricate data using AmCharts

I received the following response from the server in JSON format: [{ "data1": { "name": "Test1", "count": 0, "amount": 0, "amtData": [ 0,0,0,0 ], "cntData": [ 0,0,0,0 ], "color": "#FF0F00" }, "data2": { ...

Chatting in the hot spring with choices

I am looking to create a customizable dialog box in AngularJS where I can pass options such as title and message based on the caller. Essentially, I want to improve upon the standard alert() function. While the documentation has information on passing par ...

Adjusting color of fixed offcanvas navbar to become transparent while scrolling

After creating a navbar with a transparent background, I am now using JavaScript to attempt changing the navigation bar to a solid color once someone scrolls down. The issue is that when scrolling, the box-shadow at the bottom of the navbar changes inste ...

Using jQuery to automatically scroll to the bottom of a div when sliding down

When a user clicks on a link to slide the div down, I want it to automatically scroll to the bottom of the div. I've attempted to use scrollTo and animate methods to achieve this effect. $('html, body').animate({ scrollTop: $("#elementID") ...

Error 404 in Angular HTTP Request

I'm encountering a 404 error while attempting to send a post request, along with a 'possibly unhandled rejection' error. Given my limited experience with Angular, any advice would be greatly appreciated. I've gone through the documentat ...

Error compiling: Cannot locate module '../../common/form' within 'src/components/time'

An attempt to import the file form.jsx into the file time.jsx resulted in an error: Error message: Module not found: Can't resolve '../../common/form' in 'src/components/time' //src //common //form.jsx //compon ...

Stop mega menu items from disappearing when hovered over

I'm currently working on a web page that features a mega menu. When I hover over the mega menu, it displays its items. However, when I try to hover over the items, they disappear. Here is the HTML code snippet: <li class="dropdown mega-dropdown m ...