How to include and use a external library inside GDevelop

I am trying to include a external library into gdevelop without any success for some time. Is there an example or explanation as to how to do that? I mean it should be straight forward but for some reason if I add the script inside the index.html file after pasting the scripts in the folders and run the preview, it automatically gets deleted.

secondly if I copy paste the code inside as js, it is not accessible inside another javascript file.

How can I add an external library inside GDevelop ?

You can just put all your code in a JavaScript event. Always worked fine for me.

That is what I thought as well but when I tried to use this library by pasting the code like shown here in the upper black screen

but when I run the preview I get this error in the logs
Screenshot%20(38)

and on going to code0.js line 23 I get this error

But this same library works just fine in normal html, so why is it not working in GDevelop?
I have been trying to solve ot for days now.

I did have that problem once with socket.io. The way I solved it is using the Dom to add a script tag for the library.

where exatly do I need to add this script tag ? is it inside the index.html present at
"C:\Users\path\AppData\Local\Temp\preview" ?

EDIT
Even after adding the script tag for the library in html as below, the error is same as before:

If you don’t know the Dom you should probably learn JavaScript before trying something like using a Js library.

What is the Dom? Excuse me but i don’t know nothing about JS

Like I just said,

If you plan to use JavaScript it might be useful to learn it :wink:

Actually, i don’t plan to learn JS but perhaps it’ll be important soon.

I’m familiar with dom in regular html/js but in Gdevelop whenever i try to add another external js file into the project and run the preview the js file gets deleted automatically.
Also even after adding the object as a image tag in html file I can’t access the image through “document.getElementById()”.

Can you please help me out here?

Could you show me your code? Mine is usually like:

const dep = document.createElement("script");
dep.src = "linkToMyDependency";
document.head.appendChild(dep);

And it works fine.

If I use this (using your hint)

runtimeScene.setBackgroundColor(100,100,240);

const dep = document.createElement("script");
dep.src = "https://webisora.com/assets/js/propeller.min.js";
document.head.appendChild(dep);

var rotateElement = runtimeScene.getObjects("knob")[0];

console.log(rotateElement);
var prop = new Propeller(rotateElement , {
	inertia: 0.99, speed: 10,
});

Then I get the error as

code0.js:30 Uncaught ReferenceError: Propeller is not defined
at Object.gdjs.riddleCode.userFunc0x78b8c8 (code0.js:30)
at Object.gdjs.riddleCode.eventsList0 (code0.js:39)
at Object.gdjs.riddleCode.eventsList2 (code0.js:138)
at gdjs.RuntimeScene.gdjs.riddleCode.func [as _eventsFunction] (code0.js:168)
at gdjs.RuntimeScene.renderAndStep (runtimescene.js:364)
at gdjs.SceneStack.step (scenestack.js:39)
at runtimegame.js:530
at gameLoop (runtimegame-pixi-renderer.js:424)

and If I use this below

runtimeScene.setBackgroundColor(100,100,240);


!function(t){var e="propeller",i={angle:0,speed:0,inertia:0,minimalSpeed:.001,minimalAngleChange:.1,step:0,stepTransitionTime:0,stepTransitionEasing:"linear",rotateParentInstantly:!1,touchElement:null},n=function(t,e){if("string"==typeof t&&(t=document.querySelectorAll(t)),t.length>1)return n.createMany(t,e);1===t.length&&(t=t[0]),this.element=t,this.active=!1,this.transiting=!1,this.update=this.update.bind(this),this.initCSSPrefix(),this.initAngleGetterSetter(),this.initOptions(e),this.initHardwareAcceleration(),this.initTransition(),this.bindHandlers(),this.addListeners(),this.update()};n.createMany=function(t,e){for(var i=[],s=0;s<t.length;s++)i.push(new n(t[s],e));return i};var s=n.prototype;s.initAngleGetterSetter=function(){Object.defineProperty(this,"angle",{get:function(){return this._angle},set:function(t){this._angle=t,this.virtualAngle=t,this.updateCSS()}})},s.bindHandlers=function(){this.onRotationStart=this.onRotationStart.bind(this),this.onRotationStop=this.onRotationStop.bind(this),this.onRotated=this.onRotated.bind(this)},s.addListeners=function(){this.listenersInstalled=!0,this.touchElement.addEventListener("touchstart",this.onRotationStart),this.touchElement.addEventListener("touchmove",this.onRotated),this.touchElement.addEventListener("touchend",this.onRotationStop),this.touchElement.addEventListener("touchcancel",this.onRotationStop),this.touchElement.addEventListener("mousedown",this.onRotationStart),this.touchElement.addEventListener("mousemove",this.onRotated),this.touchElement.addEventListener("mouseup",this.onRotationStop),this.touchElement.addEventListener("mouseleave",this.onRotationStop),this.touchElement.addEventListener("dragstart",this.returnFalse),this.touchElement.ondragstart=this.returnFalse},s.removeListeners=function(){this.listenersInstalled=!1,this.touchElement.removeEventListener("touchstart",this.onRotationStart),this.touchElement.removeEventListener("touchmove",this.onRotated),this.touchElement.removeEventListener("touchend",this.onRotationStop),this.touchElement.removeEventListener("touchcancel",this.onRotationStop),this.touchElement.removeEventListener("mousedown",this.onRotationStart),this.touchElement.removeEventListener("mousemove",this.onRotated),this.touchElement.removeEventListener("mouseup",this.onRotationStop),this.touchElement.removeEventListener("mouseleave",this.onRotationStop),this.touchElement.removeEventListener("dragstart",this.returnFalse)},s.bind=function(){!0!==this.listenersInstalled&&this.addListeners()},s.unbind=function(){!0===this.listenersInstalled&&(this.removeListeners(),this.onRotationStop())},s.stop=function(){this.speed=0,this.onRotationStop()},s.onRotationStart=function(t){this.initDrag(),this.active=!0,void 0!==this.onDragStart&&this.onDragStart(),!1===this.rotateParentInstantly&&t.stopPropagation()},s.onRotationStop=function(){void 0!==this.onDragStop&&!0===this.active&&this.onDragStop(),this.active=!1},s.onRotated=function(t){!0===this.active&&(t.stopPropagation(),t.preventDefault(),void 0!==t.targetTouches&&void 0!==t.targetTouches[0]?this.lastMouseEvent={x:t.targetTouches[0].clientX,y:t.targetTouches[0].clientY}:this.lastMouseEvent={x:t.clientX,y:t.clientY})},s.update=function(){void 0!==this.lastMouseEvent&&!0===this.active&&this.updateAngleToMouse(this.lastMouseEvent),this.updateAngle(),this.applySpeed(),this.applyInertia(),Math.abs(this.lastAppliedAngle-this._angle)>=this.minimalAngleChange&&!1===this.transiting&&(this.updateCSS(),this.blockTransition(),void 0!==this.onRotate&&"function"==typeof this.onRotate&&this.onRotate.bind(this)(),this.lastAppliedAngle=this._angle),window.requestAnimFrame(this.update)},s.updateAngle=function(){this.step>0?this._angle=this.getAngleFromVirtual():this._angle=this.normalizeAngle(this.virtualAngle)},s.getAngleFromVirtual=function(){return Math.ceil(this.virtualAngle/this.step)*this.step},s.normalizeAngle=function(t){var e=t;return(e%=360)<0&&(e=360+e),e},s.differenceBetweenAngles=function(t,e){var i=t*(Math.PI/180),n=e*(Math.PI/180),s=Math.atan2(Math.sin(i-n),Math.cos(i-n))*(180/Math.PI);return Math.round(100*s)/100},s.applySpeed=function(){this.inertia>0&&0!==this.speed&&!1===this.active&&(this.virtualAngle+=this.speed)},s.applyInertia=function(){this.inertia>0&&(Math.abs(this.speed)>=this.minimalSpeed?(this.speed=this.speed*this.inertia,!1===this.active&&Math.abs(this.speed)<this.minimalSpeed&&void 0!==this.onStop&&this.onStop()):0!==this.speed&&(this.speed=0))},s.updateAngleToMouse=function(t){var e=this.element.getBoundingClientRect(),s=e.left+e.width/2,o=e.top+e.height/2,a=(Math.atan2(t.y-o,t.x-s)+Math.PI)*n.radToDegMulti;if(void 0===this.lastMouseAngle&&(this.lastElementAngle=this.virtualAngle,this.lastMouseAngle=a),this.stepTransitionTime!==i.stepTransitionTime)this.speed=this.mouseDiff=this.differenceBetweenAngles(a,this.lastMouseAngle),this.virtualAngle=this.lastElementAngle+this.mouseDiff,this.lastElementAngle=this.virtualAngle,this.lastMouseAngle=a;else{var r=this.virtualAngle;this.mouseDiff=a-this.lastMouseAngle,this.virtualAngle=this.lastElementAngle+this.mouseDiff;var h=this.virtualAngle;this.speed=this.differenceBetweenAngles(h,r)}},s.initDrag=function(){this.speed=0,this.lastMouseAngle=void 0,this.lastElementAngle=void 0,this.lastMouseEvent=void 0},s.initOptions=function(t){t=t||i,this.touchElement=document.querySelectorAll(t.touchElement)[0]||this.element,this.onRotate=t.onRotate||t.onrotate,this.onStop=t.onStop||t.onstop,this.onDragStop=t.onDragStop||t.ondragstop,this.onDragStart=t.onDragStart||t.ondragstart,this.step=t.step||i.step,this.stepTransitionTime=t.stepTransitionTime||i.stepTransitionTime,this.stepTransitionEasing=t.stepTransitionEasing||i.stepTransitionEasing,this.angle=t.angle||i.angle,this.speed=t.speed||i.speed,this.inertia=t.inertia||i.inertia,this.minimalSpeed=t.minimalSpeed||i.minimalSpeed,this.lastAppliedAngle=this.virtualAngle=this._angle=t.angle||i.angle,this.minimalAngleChange=this.step!==i.step?this.step:i.minimalAngleChange,this.rotateParentInstantly=t.rotateParentInstantly||i.rotateParentInstantly},s.initCSSPrefix=function(){void 0===n.cssPrefix&&(void 0!==document.body.style.transform?n.cssPrefix="":void 0!==document.body.style.mozTransform?n.cssPrefix="-moz-":void 0!==document.body.style.webkitTransform?n.cssPrefix="-webkit-":void 0!==document.body.style.msTransform&&(n.cssPrefix="-ms-"))},s.initHardwareAcceleration=function(){this.accelerationPostfix="";var t,e=document.createElement("p"),i={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};document.body.insertBefore(e,null);for(var s in i)void 0!==e.style[s]&&(e.style[s]="translate3d(1px,1px,1px)",t=window.getComputedStyle(e).getPropertyValue(i[s]));document.body.removeChild(e),!0===(void 0!==t&&t.length>0&&"none"!==t)&&(this.accelerationPostfix="translateZ(0)",this.element.style[n.cssPrefix+"transform"]=this.accelerationPostfix,this.updateCSS())},s.initTransition=function(){if(this.stepTransitionTime!==i.stepTransitionTime){var t="all "+this.stepTransitionTime+"ms "+this.stepTransitionEasing;this.element.style[n.cssPrefix+"transition"]=t}},s.updateCSS=function(){this.element.style[n.cssPrefix+"transform"]="rotate("+this._angle+"deg) "+this.accelerationPostfix},s.blockTransition=function(){if(this.stepTransitionTime!==i.stepTransitionTime){var t=this;setTimeout(function(){t.transiting=!1},this.stepTransitionTime),this.transiting=!0}},s.returnFalse=function(){return!1},void 0!==t.$&&($.propeller={},$.propeller.propellers=[],$.fn[e]=function(t){return this.each(function(){if(!$.data(this,"plugin_"+e)){var i=new n(this,t);$.data(this,"plugin_"+e,i),$.propeller.propellers.push(i)}})}),n.deg2radians=2*Math.PI/360,n.radToDegMulti=57.29577951308232,t.Propeller=n}(window),window.requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)};


var rotateElement = runtimeScene.getObjects("knob")[0];

console.log(rotateElement);
var prop = new Propeller(rotateElement , {
		inertia: 0.99, speed: 10,
	});

Then I get this error

Uncaught TypeError: Cannot set property 'transform' of undefined
    at n.s.updateCSS (code0.js:21)
    at n.set (code0.js:21)
    at n.s.initOptions (code0.js:21)
    at new n (code0.js:21)
    at Object.gdjs.riddleCode.userFunc0x6d9520 (code0.js:29)
    at Object.gdjs.riddleCode.eventsList0 (code0.js:38)
    at Object.gdjs.riddleCode.eventsList2 (code0.js:137)
    at gdjs.RuntimeScene.gdjs.riddleCode.func [as _eventsFunction] (code0.js:167)
    at gdjs.RuntimeScene.renderAndStep (runtimescene.js:364)
    at gdjs.SceneStack.step (scenestack.js:39)

Everything from the temp\preview folder is deleted and rewritten every time you start a preview. Therefore you cannot put a library there or call it up in the index.
But you can do it in Programs\gdevelop\resources\GDJS\Runtime\index.html. Near row 27. From there the files are automatically copied to the preview and export folder. Unfortunately not own files, so you can use an online url to the library or add it after the export(if it is html).

Tested today with jquery.

2 Likes

You need to wait for it to load as script loading is non blocking. What I usually do is put my code in fhe onload handler just before appending to head:

dep.onload = function () {
    // Do stuff with the library
}

after using the library after loading also the error in the logs is the same.Here is the code I used

runtimeScene.setBackgroundColor(100,100,240);
const dep = document.createElement("script");
dep.src = "https://webisora.com/assets/js/propeller.min.js";
document.head.appendChild(dep);


var rotateElement = runtimeScene.getObjects("knob")[0];

dep.onload = function () {
       
    console.log(rotateElement);
    var prop = new Propeller(rotateElement , {
		inertia: 0.99, speed: 10,
	});
    }

and the error is still

Uncaught TypeError: Cannot set property 'transform' of undefined
    at n.s.updateCSS (propeller.min.js:1)
    at n.set (propeller.min.js:1)
    at n.s.initOptions (propeller.min.js:1)
    at new n (propeller.min.js:1)
    at HTMLScriptElement.dep.onload (code0.js:32)

which is the same as before:

Then your library is just broken I guess ¯\_(ツ)_/¯ can’t help much with that, you’ll have to contact the maintainer of your library.

Actually i have tried the library in simple html and it works fine with the same code as I am using in GDevelop. Here is the code in simple html, you can check it (you can put any image in place of mine with same name).

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    <div class="webisora-demo">
        <p id="instructions"></p>
        <div id="container">
            <img id="rotate-this" src="Rotater2.png" alt="" />
        </div>
   </div>
   <script src="https://webisora.com/assets/js/propeller.min.js"></script>

   <<script type="text/javascript">
     startRotation();
function startRotation() {



	var rotateElement = document.getElementById('rotate-this');
	new Propeller(rotateElement , {
		inertia: 0, speed: 10,
	});

}
   </script>

  </body>
</html>

@jack I was playing around with the index.html and I am stuck at some points.

I have a tag and a function say myfunc() inside the script tag.

Now if I have a button object placed on screen by drag and drop method in gdevelop, how can I detect the click on this button object (which is added from inside the GDevelop) in the script that i am writing inside the index.html. and the on click call this myfunc() .

EDIT

basically i wanted to ask that is it possible to access that object in script which was added by drag and drop in GDevelope. So that i can add onclick like listeners on it.