Call to undefined function Drupal\threejs_fields\Plugin\Field\FieldWidget\file_create_url()

Created on 2 February 2023, almost 2 years ago
Updated 13 March 2024, 8 months ago

Problem/Motivation

Error when uploading an STL file. The complete error is:
Error: Call to undefined function Drupal\threejs_fields\Plugin\Field\FieldWidget\file_create_url() in Drupal\threejs_fields\Plugin\Field\FieldWidget\ThreeJSFileWidget::process() (line 138 of ..../modules/threejs/modules/threejs_fields/src/Plugin/Field/FieldWidget/ThreeJSFileWidget.php).

Steps to reproduce

Installed and configured the module on Drupal 10.0.2

Proposed resolution

Remove deprecated funcions. Replace file_create_url() with \Drupal::service('file_url_generator')->generateAbsoluteString(($uri))

Generally, this module is not ready for Drupal 10, the library dependencies need to be changed (for example from core/jquery.once to core/once) and the loading priority should be adjusted, for example
<script src="//cdn.jsdelivr.net/npm/three@0.147.0/examples/js/loaders/STLLoader.js"></script> is called before <script src="//threejs.org/build/three.min.js"></script> and it generates an error "THREE is not defined"

🐛 Bug report
Status

Fixed

Version

1.0

Component

Code

Created by

🇮🇹Italy smurfxx

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @smurfxx
  • 🇫🇷France lazzyvn paris

    can you make patch please ? i will test right now
    How can i set priority for threejs.org/build/three.min.js before loaders?

  • 🇮🇹Italy smurfxx

    I'm sorry but I'm studying for drupal module development and I don't know how to create patches, I can only tell you where module generates errors and why.

  • 🇫🇷France lazzyvn paris

    Try Dev version. I fixed some bug for drupal 10

  • 🇮🇹Italy smurfxx

    Thank you lazzyvn, I tried the dev version but when I go to view the field in a node i get the following error on chrome console:
    Uncaught TypeError: $(...).once is not a function

    I see you declared core/once correctly in the threejs.libraries.yml but maybe you need to fix the javascripts with this guide: https://www.drupal.org/node/3158256

  • First commit to issue fork.
  • 🇫🇷France lazzyvn paris

    I try with
    once("initiate-threejs", ".canvas-container .threejs", context).forEach(() => {

    Can you test version dev if it works

  • 🇮🇹Italy smurfxx

    I applied your patch on threejs.init.js but with both STL files and obj files I get this javascript error:
    Uncaught TypeError: Cannot read properties of undefined (reading 'split')

  • 🇫🇷France lazzyvn paris

    try again dev branch i test with obj it works

  • 🇮🇹Italy smurfxx

    I updated to last dev release, but I think you forgot to change the function "file_create_url($model_uri)" to "\Drupal::service('file_url_generator')->generateAbsoluteString(($model_uri))" and now the error "THREE is not defined" is back.

    Did you changed only the javascript and not the other things?

  • 🇫🇷France lazzyvn paris

    Maybe you are not getting the latest DEV version, delete module and composer require again
    I release a new version 1.0.4, also on the dev version. I test for my project on drupal 10, it works without error.
    can you test again and report error for your type. if it doesn't work, can you replace //threejs.org/build/three.min.js by //cdn.jsdelivr.net/npm/three@0.147.0 maybe threejs load faster.

  • 🇮🇹Italy smurfxx

    Ok I installed your module from zero, now I have ver. 1.0.4 and I made these tests:
    - viewing stl file generates this error: TypeError: t.updateWorldMatrix is not a function --> STLLoader.js:83
    - viewing obj file I don't have errors but I see the 3d object so big that I can't understand what is it, if I try to zoom out the object disappears in a white frame even if I setted a black background

    I used also //cdn.jsdelivr.net/npm/three@0.147.0 as threejs source and it works really well!

  • 🇫🇷France lazzyvn paris

    If I have more time i will fix STLLoader.
    another 3D option which I plan to add as an extension but I have no time to continue. Orbit is good enough for my project

  • 🇮🇹Italy smurfxx

    Thank you very much for your support, I hope you will have time to make this module the best 3D viewer for Drupal ;)

  • 🇨🇦Canada joseph.olstad

    awesome! Great work @lazzyvn

  • 🇫🇷France lazzyvn paris

    i found
    https://stackoverflow.com/questions/59075004/object-updateworldmatrix-is...

    try yourself in threejs.init.js code if it works i will add for stl

  • 🇮🇹Italy smurfxx

    I changed some lines of threejs.init.js :)

    (function ($,Drupal, settings, once) {
      Drupal.behaviors.ThreeJSinit = {
        attach: function (context) {
          $(once("initiate-threejs", ".canvas-container .threejs", context)).each(function () {
            const file = $(this).data('model');
            const extension = file.split('.').pop().toUpperCase();
            const loaderName = extension + 'Loader';
            let loader = new THREE[loaderName]();
            let canvas = $(this).get(0);
            let renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
            renderer.setPixelRatio(window.devicePixelRatio);
    
            renderer.setSize(canvas.clientWidth, canvas.clientHeight);
            renderer.gammaFactor = 2.2;
            renderer.outputEncoding = THREE.sRGBEncoding;
            renderer.physicallyCorrectLights = true;
    
            const width = $(this).width();
            const height = $(this).height();
            let scene = new THREE.Scene();
            scene.background = new THREE.Color(settings.threejs.backgroundColor);
    //      let camera = new THREE.PerspectiveCamera(1, width / height, 0.1, 50);
            let camera = new THREE.PerspectiveCamera(35, width / height, 1, 500); // New setting
    //      camera.position.set(settings.threejs.cameraX, settings.threejs.cameraY, settings.threejs.cameraZ);
            camera.position.set( 0, -9, 6);
            camera.up.set( 0, 0, 1 ); // New setting
            
            scene.add( camera );
    
            let ambient = new THREE.AmbientLight(0xffffff, 0.3);
            scene.add(ambient);
            let keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30, 100%, 75%)'), 1.0);
            keyLight.position.set(-100, 0, 100);
    
            let fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240, 100%, 75%)'), 0.75);
            fillLight.position.set(100, 0, 100);
    
            let backLight = new THREE.DirectionalLight(0xffffff, 1.0);
            backLight.position.set(100, 0, -100).normalize();
    
            scene.add(keyLight);
            scene.add(fillLight);
            scene.add(backLight);
    
            let mesh;
            if (extension != 'STL') {
                loader.load(file, function (object) {
        
                  var objBbox = new THREE.Box3().setFromObject(object);
        
                  // Geometry vertices centering to world axis
                  var bboxCenter = objBbox.getCenter(new THREE.Vector3()).clone();
                  bboxCenter.multiplyScalar(-1);
        
                  object.traverse(function (child) {
                    if (child instanceof THREE.Mesh) {
                      child.geometry.translate(bboxCenter.x, bboxCenter.y, bboxCenter.z);
                    }
                    if (settings.threejs.SphereMapUrl != '') {
                      const texture = new THREE.TextureLoader().load(settings.threejs.SphereMapUrl);
                      const material = new THREE.MeshBasicMaterial({map: texture});
                      child.material = material;
                    }
                  });
        
                  objBbox.setFromObject(object); // Update the bounding box
        
                  scene.add(object);
                });
            } else {
                var material = new THREE.MeshPhongMaterial( { color: 0x004C00, specular: 0x111111, shininess: 300 } );
                var grid = new THREE.GridHelper( 500, 500, 0x444444, 0x555555 );
                grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
                scene.add( grid );
                loader.load( file, function ( geometry ) {
            	var mesh = new THREE.Mesh( geometry, material );
        
            	mesh.position.set( 0, 0, 0 );
            	mesh.rotation.set( 0, 0, 0 );
            	mesh.scale.set( .08, .08, .08 );
        
            	mesh.castShadow = true;
            	mesh.receiveShadow = true;
        
            	scene.add( mesh );
            	render();
                });
            }
    
            // Add OrbitControls so that we can pan around with the mouse.
            let controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = false;
            controls.dampingFactor = 0.25;
            controls.enableZoom = true;
            controls.autoRotate = true;
            controls.autoRotateSpeed = 1;
            render();
    
            function render() {
              // render using requestAnimationFrame
              requestAnimationFrame(render);
              if (mesh && settings.threejs.InitRotationX != '') {
                mesh.rotation.x -= 0.01;
              }
              if (mesh && settings.threejs.InitRotationY != '') {
                mesh.rotation.y -= 0.01;
              }
              if (mesh && settings.threejs.InitRotationZ != '') {
                mesh.rotation.z -= 0.01;
              }
              renderer.render(scene, camera);
            }
          });
        }
      };
    }(jQuery, Drupal, drupalSettings, once));
    

    As you can see I focused on STL output, adding a grid and changing the perspective camera, that was the reason why the object was disappearing when zooming out.

    These settings are good for a canvas with width of 100% of it's container (1170px for a bootstrap container), I think the next steps are:
    - setting a color for the texture of the object (as you can see I foced the green color for STLs)
    - setting an option to display or not the grid
    - setting for a default zoom

    If you need a hand I can help you, I'll learn how to generate patches so we can develop more faster!

  • 🇫🇷France lazzyvn paris

    it think when we load the model with the extension loader => SLT Loader - push the model in the box (size of the box defined in parameter) The problem is that the slt model can't push in the box.

    for patch it is very simple
    remove module.
    clone from git (click on version module you will get) https://git.drupalcode.org/project/threejs.git

    after modify module you just run

    git diff master..localbranch > file.patch

    upload file patch that's all

  • 🇫🇷France lazzyvn paris

    update the dev. Now it loads stl but I can push the object into the box. if your object is too big, you can't see it

  • Status changed to Needs review 9 months ago
  • 🇮🇳India deepak tomar

    I have created a patch for the following issue.

  • Status changed to Fixed 9 months ago
  • 🇫🇷France lazzyvn paris

    fixed in dev version

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024