I hate prototype it made high fidelity much more difficult


#1

High fidelity easy to use ? Not with javascript and especially not with prototyping.
It’s really the biggest fail for me what made high fidelity javascript a nightmare. Instead of using normal functions you can call or get called by event like C# and delphi etc do.

It start to get comple with prototypes. and so far not found the correct example that explains it correct. also it need to be example for script inside entity. If C# in sansar works better the have a jump ahead. C# in visual studio works at leats not bad. but there’s enough good documentation to.

Anyway, i can send something from child entity.

Entities.callEntityMethod(parentID, 'DOORhandleTouched');

Now after just tring and thingking and reading a bit i tried.
This is the easy and readable and good way to work with porototypes.
in a few years it mabye can be improved. But, it fails to respond. SO i do soemthing wrong. but this the only way it works for without any error.

function this.prototype.DOORhandleTouched = function() 
{
	print("DOORhandleTouched");
}

Still hate prototype., biggest fail in high fidelity.
Anyway, i betetr stop working on my script ,
because i dont know how to fix it right now.

prototypoes looks a bit tyhe same how it works in delphi. But then i still not understand why there are no errors in m example above but it still fail.


#2

Ok, that example does not work to. just because it did look to work. unless i did see in the *just one edge szied) font that the path where wrong.
Try to figure out prototyping but it’s simple a hell with javascript.

ADD:
I got it working, only my brain is blurred that i still need to understand why this is needed and how it works this time…

    function ParamsEntity() 
	{
        return;
    }	
	
	ParamsEntity.prototype = 
	{
		DOORhandleTouched: function() 
		{
			print("DOORhandleTouched");
		}
	}
	
	return new ParamsEntity();

Still think that this can be done much more simple without prototypes and just with event that get trigger when you press a button and a few if then lines that compare the json data you get from the controller button event. But this… yiks.

ADD:
Ands now nothing respon danymore, at least only tried the mouseclick. and that stopped responding. I tried to add it in the prototype section but that generate errors. So now i think am really stuck.

 (function()
{
	var Ent;	
	var parentID;
	
	this.preload=function(entityID)
	{ 
		Ent = entityID;
        parentID = Entities.getEntityProperties(Ent, ['parentID']).parentID;
		print("Parent EntID  "+parentID);		
	}	

    function sendmessage()
	{		
        print("message send");
		Entities.callEntityMethod(parentID, 'DOORhandleTouched');
    };
	
    this.clickDownOnEntity = function(entityID, mouseEvent)
	{ 
		print("doorhandle clicked");
		sendmessage();
    }	
	

	//-------------
	
    function ControllerInteractable() 
	{
        return;
    }	
	
	ControllerInteractable.prototype = 
	{
		startNearTrigger: function() 
		{
			print("Controller Triggered near");
			sendmessage();
		}	
	}
	
	return new ControllerInteractable();

})

This does not send anything anymore to the parent. It worked before i did add the prototype disaster in.


#3
function this.prototype.DOORhandleTouched = function() 
{
	print("DOORhandleTouched");
}

this is context sensative and you should avoid using this.prototype: use [ObjectNameHere].prototype instead.

 (function()
{
	var Ent;	
	var parentID;
	
	this.preload=function(entityID)
	{ 
		Ent = entityID;
        parentID = Entities.getEntityProperties(Ent, ['parentID']).parentID;
		print("Parent EntID  "+parentID);		
	}	

    function sendmessage()
	{		
        print("message send");
		Entities.callEntityMethod(parentID, 'DOORhandleTouched');
    };
	
    this.clickDownOnEntity = function(entityID, mouseEvent)
	{ 
		print("doorhandle clicked");
		sendmessage();
    }	
	

	//-------------
	
    function ControllerInteractable() 
	{
        return;
    }	
	
	ControllerInteractable.prototype = 
	{
		startNearTrigger: function() 
		{
			print("Controller Triggered near");
			sendmessage();
		}	
	}
	
	return new ControllerInteractable();

})

Above will not work either because parentID is never set. as this.preload is never reached as your return a ControllerInteractable to be used by the entity: this never triggers the preload method.

I suggest using my library script for scripting if you cannot wrap your head around prototype. it wraps everything into so that you do not have to write a prototype thing and handles a lot of things one would miss without advanced scripting know how.

Basically, The above.

Door

(function(){
  var Entity;Overlay=function(a){this.properties=a?a:{},this.properties.scale=this.properties.scale?this.properties.scale:{x:1,y:1,z:1},this.properties.position=this.properties.position?this.properties.position:MyAvatar.position,this.properties.rotation=this.properties.rotation?this.properties.rotation:Quat.ZERO,this.properties.color=this.properties.color?this.properties.color:{red:255,green:255,blue:255},this.properties.alpha=this.properties.alpha?this.properties.alpha:1,this.type=this.properties.type?this.properties.type:"cube","line3d"===this.properties.type?(this.properties.start=this.properties.start?this.properties.start:Vec3.ZERO,this.properties.end=this.properties.end?this.properties.end:Vec3.ZERO,this.properties.glow=this.properties.glow?this.properties.glow:0):this.properties.solid=!!this.properties.solid,this.callbacks={},this._filter=[];var b=this;this.scriptEnding=function(){b.deleteOverlay(),Script.scriptEnding.disconnect(b.scriptEnding)},Script.scriptEnding.connect(b.scriptEnding)},Overlay.prototype={properties:null,id:-1,_filter:null,callbacks:null,filter:function(a){return this.id!==-1?(this._filter=a,this.sync(a)):this},addOverlay:function(){return this.id===-1&&(this.id=Overlays.addOverlay(this.type,this.properties)),this},deleteOverlay:function(){try{this.id!==-1&&Overlays.deleteOverlay(this.id)}catch(a){print("Overlay does no longer exist.")}return this.id=-1,this},updateOverlay:function(){try{this.id!==-1&&Overlays.editOverlay(this.id,this.properties)}catch(a){print("OWrap: Overlay does not exist in world.")}return this},editProperties:function(a){for(var b in a)this.properties[b]=a[b];return this}},Entity=function(a){if(null===a||void 0===a||"function"==typeof a){var b=this;this.preload="function"==typeof a?a:function(a){b.id=a,Object.keys(b.callbacks).forEach(function(c){b[c]=b.callbacks[c],Script.addEventHandler(a,c,b[c])})},this.callbacks={},this.properties={},this._filter=[]}else"string"==typeof a?(this.properties=Entities.getEntityProperties(a),this.properties&&null!==this.properties&&0!==this.properties.length?this.id=a:(this.id=null,this.properties={})):this.properties=a;this.callbacks={},this._filter=[]},Entity.prototype={properties:null,id:null,_filter:null,callbacks:null,setPreload:function(a){return this.preload=a,this},filter:function(a){return null!==this.id&&void 0!==this.id?(this._filter=a,this.sync(a)):this},addEntity:function(){return null===this.id&&void 0!==this.id&&(this.id=Entities.addEntity(this.properties)),this},deleteEntity:function(){try{null!==this.id&&void 0!==this.id&&Entities.deleteEntity(this.id)}catch(a){print("Entity does no longer exist.")}return this.id=null,this},sync:function(a){if(null!==this.id&&void 0!==this.id){a=null===a||void 0===a?this._filter:a;var b=Entities.getEntityProperties(this.id,a);void 0!==b.id?this.properties=b:this.id=null}return this._filter=[],this},editProperties:function(a){for(var b in a)this.properties[b]=a[b];return this},callMethod:function(a,b){return null===this.id||void 0===this.id?this:(Entities.callEntityMethod(this.id,a,b),this)},unbind:function(a){return null===this.id||void 0===this.id?this:null===this.callbacks[a]?this:(Script.removeEventHandler(this.id,a,this.callbacks[a]),delete this.callbacks[a],this)},bind:function(a,b,c){print("binding method "+a+this.id),void 0===c&&(c=!0),null!==this.callbacks[a]&&this.unbind(a,this.callbacks[a]);var d=this;return this.callbacks[a]=c?function(){b(d,this.arguments)}:b,null!==this.id&&void 0!==this.id&&Script.addEventHandler(this.id,a,b),this},clearInteractions:function(){return this.unbind("startFarTrigger").unbind("clickDownOnEntity").unbind("continueFarTrigger").unbind("holdingClickOnEntity").unbind("continueFarTrigger").unbind("holdingClickOnEntity"),this},clearEquip:function(){return this.unbind("onEquip").unbind("startEquip").unbind("continueEquip"),this},setOnEquip:function(a){var b=this,c=function(c,d){var e="left"===d[0]?Controller.Standard.LT:Controller.Standard.RT;a(b,e,d)};return null===this.id?this.startEquip=c:this.bind("onEquip",c,!1),b},setOnEquipTrigger:function(a){var b=this,c=function(c,d){var e="left"===d[0]?Controller.Standard.LT:Controller.Standard.RT,f=Controller.getValue(e);a(b,e,f,d)};return null===this.id?this.continueEquip=c:this.bind("continueEquip",c,!1),b},setOnUnequip:function(a){var b=this,c=function(c,d){var e="left"===d[0]?Controller.Standard.LT:Controller.Standard.RT,f=Controller.getValue(e);a(b,e,f,d)};return null===this.id?this.releaseEquip=c:this.bind("releaseEquip",c,!1),b},setInteractionStart:function(a){var b=this,c=function(){a(b,{button:"hand"})},d=function(c,d){a(b,d)};return null===this.id?(this.clickDownOnEntity=d,this.startFarTrigger=c):this.bind("startFarTrigger",c,!1).bind("clickDownOnEntity",d,!1),this},setInteractionHold:function(a){var b=this,c=function(){a(b,{button:"hand"})},d=function(c,d){a(b,d)};return null===this.id?(this.continueFarTrigger=c,this.holdingClickOnEntity=d):this.bind("continueFarTrigger",c,!1).bind("holdingClickOnEntity",d,!1),this},setInteractionStop:function(a){var b=this,c=function(){a(b,{button:"hand"})},d=function(c,d){a(b,d)};return null===this.id?(this.stopFarTrigger=c,this.clickReleaseOnEntity=d):this.bind("stopFarTrigger",c,!1).bind("clickReleaseOnEntity",d,!1),this},updateEntity:function(){try{null!==this.id&&Entities.editEntity(this.id,this.getProperties())}catch(a){print("EWrap: Entity does not exist in world.")}return this.sync()},getProperties:function(a){if(a=null===a||void 0===a?this._filter:a,0===a.length)return this.properties;var b={};return a.forEach(function(c){b.push(this.properties[a[index]])}),b}};
  // Above is the "library" until actual libraries are supported, Importing only Entity.
  // Return Entity Object that has a DOORhandleTouched callback bound
  return new Entity().bind("DOORhandleTouched", function(derp) {
    print("blah");
  });
});

Handle

(function() {
  var Entity;
  Overlay=function(a){this.properties=a?a:{},this.properties.scale=this.properties.scale?this.properties.scale:{x:1,y:1,z:1},this.properties.position=this.properties.position?this.properties.position:MyAvatar.position,this.properties.rotation=this.properties.rotation?this.properties.rotation:Quat.ZERO,this.properties.color=this.properties.color?this.properties.color:{red:255,green:255,blue:255},this.properties.alpha=this.properties.alpha?this.properties.alpha:1,this.type=this.properties.type?this.properties.type:"cube","line3d"===this.properties.type?(this.properties.start=this.properties.start?this.properties.start:Vec3.ZERO,this.properties.end=this.properties.end?this.properties.end:Vec3.ZERO,this.properties.glow=this.properties.glow?this.properties.glow:0):this.properties.solid=!!this.properties.solid,this.callbacks={},this._filter=[];var b=this;this.scriptEnding=function(){b.deleteOverlay(),Script.scriptEnding.disconnect(b.scriptEnding)},Script.scriptEnding.connect(b.scriptEnding)},Overlay.prototype={properties:null,id:-1,_filter:null,callbacks:null,filter:function(a){return this.id!==-1?(this._filter=a,this.sync(a)):this},addOverlay:function(){return this.id===-1&&(this.id=Overlays.addOverlay(this.type,this.properties)),this},deleteOverlay:function(){try{this.id!==-1&&Overlays.deleteOverlay(this.id)}catch(a){print("Overlay does no longer exist.")}return this.id=-1,this},updateOverlay:function(){try{this.id!==-1&&Overlays.editOverlay(this.id,this.properties)}catch(a){print("OWrap: Overlay does not exist in world.")}return this},editProperties:function(a){for(var b in a)this.properties[b]=a[b];return this}},Entity=function(a){if(null===a||void 0===a||"function"==typeof a){var b=this;this.preload="function"==typeof a?a:function(a){b.id=a,Object.keys(b.callbacks).forEach(function(c){b[c]=b.callbacks[c],Script.addEventHandler(a,c,b[c])})},this.callbacks={},this.properties={},this._filter=[]}else"string"==typeof a?(this.properties=Entities.getEntityProperties(a),this.properties&&null!==this.properties&&0!==this.properties.length?this.id=a:(this.id=null,this.properties={})):this.properties=a;this.callbacks={},this._filter=[]},Entity.prototype={properties:null,id:null,_filter:null,callbacks:null,setPreload:function(a){return this.preload=a,this},filter:function(a){return null!==this.id&&void 0!==this.id?(this._filter=a,this.sync(a)):this},addEntity:function(){return null===this.id&&void 0!==this.id&&(this.id=Entities.addEntity(this.properties)),this},deleteEntity:function(){try{null!==this.id&&void 0!==this.id&&Entities.deleteEntity(this.id)}catch(a){print("Entity does no longer exist.")}return this.id=null,this},sync:function(a){if(null!==this.id&&void 0!==this.id){a=null===a||void 0===a?this._filter:a;var b=Entities.getEntityProperties(this.id,a);void 0!==b.id?this.properties=b:this.id=null}return this._filter=[],this},editProperties:function(a){for(var b in a)this.properties[b]=a[b];return this},callMethod:function(a,b){return null===this.id||void 0===this.id?this:(Entities.callEntityMethod(this.id,a,b),this)},unbind:function(a){return null===this.id||void 0===this.id?this:null===this.callbacks[a]?this:(Script.removeEventHandler(this.id,a,this.callbacks[a]),delete this.callbacks[a],this)},bind:function(a,b,c){print("binding method "+a+this.id),void 0===c&&(c=!0),null!==this.callbacks[a]&&this.unbind(a,this.callbacks[a]);var d=this;return this.callbacks[a]=c?function(){b(d,this.arguments)}:b,null!==this.id&&void 0!==this.id&&Script.addEventHandler(this.id,a,b),this},clearInteractions:function(){return this.unbind("startFarTrigger").unbind("clickDownOnEntity").unbind("continueFarTrigger").unbind("holdingClickOnEntity").unbind("continueFarTrigger").unbind("holdingClickOnEntity"),this},clearEquip:function(){return this.unbind("onEquip").unbind("startEquip").unbind("continueEquip"),this},setOnEquip:function(a){var b=this,c=function(c,d){var e="left"===d[0]?Controller.Standard.LT:Controller.Standard.RT;a(b,e,d)};return null===this.id?this.startEquip=c:this.bind("onEquip",c,!1),b},setOnEquipTrigger:function(a){var b=this,c=function(c,d){var e="left"===d[0]?Controller.Standard.LT:Controller.Standard.RT,f=Controller.getValue(e);a(b,e,f,d)};return null===this.id?this.continueEquip=c:this.bind("continueEquip",c,!1),b},setOnUnequip:function(a){var b=this,c=function(c,d){var e="left"===d[0]?Controller.Standard.LT:Controller.Standard.RT,f=Controller.getValue(e);a(b,e,f,d)};return null===this.id?this.releaseEquip=c:this.bind("releaseEquip",c,!1),b},setInteractionStart:function(a){var b=this,c=function(){a(b,{button:"hand"})},d=function(c,d){a(b,d)};return null===this.id?(this.clickDownOnEntity=d,this.startFarTrigger=c):this.bind("startFarTrigger",c,!1).bind("clickDownOnEntity",d,!1),this},setInteractionHold:function(a){var b=this,c=function(){a(b,{button:"hand"})},d=function(c,d){a(b,d)};return null===this.id?(this.continueFarTrigger=c,this.holdingClickOnEntity=d):this.bind("continueFarTrigger",c,!1).bind("holdingClickOnEntity",d,!1),this},setInteractionStop:function(a){var b=this,c=function(){a(b,{button:"hand"})},d=function(c,d){a(b,d)};return null===this.id?(this.stopFarTrigger=c,this.clickReleaseOnEntity=d):this.bind("stopFarTrigger",c,!1).bind("clickReleaseOnEntity",d,!1),this},updateEntity:function(){try{null!==this.id&&Entities.editEntity(this.id,this.getProperties())}catch(a){print("EWrap: Entity does not exist in world.")}return this.sync()},getProperties:function(a){if(a=null===a||void 0===a?this._filter:a,0===a.length)return this.properties;var b={};return a.forEach(function(c){b.push(this.properties[a[index]])}),b}};
  // Above is the "library" until actual libraries are supported, Importing only Entity.

  // Return an Entity Object that has an Interaction bound to it (Mouse click, Far grab by default)
  return new Entity().setInteractionStart(function(instance, m) {
    var doorID = instance.sync(["parentID"]).properties.parentID;
    var door = new Entity(doorID); // Just bind the ID to a JS Entity object
    print("trying to call")
    door.callMethod("DOORhandleTouched"); // Call Door method DOORHandleTouched
  });
});


BUT! Instead of doing that in two separate scripts, I suggest doing everything in a single script

Basically, just name the child object of a specific name, then look for that object from the object’s children using, and then just checking the names for the right one which matches the handle.

Entities.getChildrenIDs

My framework doesnt support that yet, but it will at somepoint.


#4

Well, your example looks spaghetti to :open_mouth:
But the parentID i just request at the wrong place then. i think i know how to fix that.

I first wanted to use only one script. but did not know how. i think i forgot the getChildrenID function. need more checking then.

I think i also figured out that there are a few type errors. That’s the problem when you not have a good IDE like visual studio.


#5

Thanks @menithal. the first problem where that i retrieved the entityID on the wrong place. easy to fix. but just not seen it.

The other problem where a stupid comma i forgot :confounded:
It works now my way. with the mouse. Now i need to think if i use the childentity or not. i think i do, but need to read the wiki first.


#6

Most of what seems spagethis is just me using JS-methods you may not be familiar with:

Basically the framework allows you to daisy chain commands
So forexample

 return new Entity().setInteractionStart(function(instance, m) {
    var doorID = instance.sync(["parentID"]).properties.parentID;
    var door = new Entity(doorID); // Just bind the ID to a JS Entity object
    print("trying to call")
    door.callMethod("DOORhandleTouched"); // Call Door method DOORHandleTouched
  });

// -------
/// Is Same as

var handle = new Entity();
var callback = function(instance, m) {
   // instance is same as above handle, but sometimes its hard to keep track of this or that. doing it this ways allows one to also chain events.
   // so i kept it to avoid having to write this or that or self, or which ever.

   instance.sync(["parentID"]); // Get this object's current parent

   var properties = instance.properties; // get this object's properties
   var doorID = properties.parentID; // Get the parent ID.
   var door = new Entity(doorID); // Get a framework instance of doorID
   door.callMethod("DOORhandleTouched"); // Call Door method DOORHandleTouched
};
handle.setInteractionStart(callback);
return handle;

There is no need to use this or that or prototype as the framework wraps it and has alot of helper methods.


#7

I think prototype can be easy. But you need to understand how to start with it.
I still would not know how to make my custom ones but that’s not a problem for now. It’s anyway a corner for the wiki to explain more about. It will help many users.

Important is that i can move formward and get away from that problem. There enough new ones ahead.


#8

I agree. Prototype is easy once you understand the syntax how it works.

But I just found my self repeating a lot of things in it when creating something thus the framework, so made it to just save time. :slight_smile:


#9

@Menithal I have one question, converted things back to one script. I know the child entity id.

But how you detect when the click on the child entity ?
From the parent script ? clickDownOnEntity seems not to handle that.


#10

Use

Script.addEventHandler(childID, methodName, function)

To bind a function to an entity.


#11

Og nice another new and undocumented command. that means this one is on the wiki , but without example. and i searched in the high fidelity directory for the keyword addEventHandler. but it’s only in the exe files.

The lack of documentation make things pretty hard for people.
Now tim e to figure out if i can figure out this command :open_mouth:

ADD: Thanks @Menithal that command works. Yes i got it working after i did remember some old script. code i used in the voxel time.

There’s one problem or bug with
Script.addEventHandler(childID, methodName, function)
It get triggered more times with one click, so i need to add a debouncer.

No debouncer needed. there’s some bug around that corner. Blames the cache again I use the same script and modify small things and press reload. For some reason high fidelity is not stopping the old scripts in the entity. or soemthing got mixed. because the old common problem come back that the log did show output from a few script versions ago. and that where still running. I did close interface and then start it again and that fixt it, until the next round.

ADD: Mabye high fideity forget to close everything when you restart a script ? @Menithal Do you know if you need to close/stop soemthing when you use
Script.addEventHandler(childID, methodName, function)
Because as soon i reload the script by pressing the reload button i start to get double print lines in the log.

Let me do some testing with unload event and remove of the event. and see if that fix the problem.

Late night ADD:

I now have add
removeEventHandler(entityIDString, entityMethodNameString, handler) // Return value
That works in combination with
Script.scriptEnding.connect(scriptEnding);
Scriptending seems not be called when you reload the entity script by pressing the reload button in edit.js. Also the script only call scriptending when i go to other domain.

Next problem is that reload or the script is not called/reloaded or reset as far i now see when im entering the sim and fly to the scripted object.

Why do i get the idea that the whole scipting in secondlife is still whacky wheels ? It does not do the thing how you expect it need todo things. :hushed:

I think i reverse everything back to my 2 script system, that is fool proof and reliable. this child entity click system is buggy as hell.


#12

It sounds like your Script.scriptEnding.connect is just never called with the function scriptEnding Id need to see the entire script to tell you whats wrong with it.


#13

For now i go work the 2 script way. Keep things easy is a good start.
Well the script get called when i leave the domain.


#14

Moved the question to new topic, because the wiki example is failing to.