<commit_before>//Check, if basics have already been defined
var org;
if (!org || !org.xml3d)
  throw new Error("xml3d.js has to be included first");

//Create global symbol org.xml3d.animation
if (!org.xml3d.animation)
	org.xml3d.animation = {};
else if (typeof org.xml3d.animation != "object")
	throw new Error("org.xml3d.animation already exists and is not an object");

// This is quirk required  to run animation manager initalization only after full
// document is loaded and all X3D interpolation elements are accesible.

// Browsers  based  on  Gecko 1.9.2 (e.g. Firefox 3.5) will only execute function
// that is set to timeout in 0 milliseconds exactly after document will be loaded
// or  as  soon  as  possible  if  document is already loaded, thus we can safely
// initalize animation manager. Such browsers can  be checked by testing value of
// document.readyState, which must be undefined.

// Other browsers may execute function  even  before loading  of  the webpage  is 
// finished, but they define document.readyState,  which allows us to detech such
// state  and  register event handler, which  will  run  the  initalization after 
// document is fully loaded.

setTimeout(function() {
	function initAnimationManager() {
		org.xml3d.debug.logInfo("Initializing Animation Manager.");
		org.xml3d.animation.animationManager = new org.xml3d.animation.XML3DAnimationManager();
		org.xml3d.animation.animationManager.init();
	};
	
	if (document.readyState == "complete" || // All major browsers except Gecko 1.9.2 or earlier.
		document.readyState == undefined) // Gecko 1.9.2 or earlier version. Document is guaranteed to be loaded when running this code.
		initAnimationManager();
	else
		window.addEventListener('load', initAnimationManager, false);
}, 0);

org.xml3d.startAnimation = function(aniID, transID, transAttr, duration, loop)
{
	return org.xml3d.animation.animationManager.startAnimation(aniID, transID, transAttr, duration, loop);
};

org.xml3d.stopAnimation = function(handle)
{
	org.xml3d.animation.animationManager.stopAnimation(handle);
};

org.xml3d.stopAllAnimations = function() 
{
	org.xml3d.animation.animationManager.stopAllAnimations();
};

org.xml3d.animation.XML3DAnimationManager = function() {
	this.interpolators = {};
	var xml3d = document.evaluate('//xml3d:xml3d', document, function() {
		return org.xml3d.xml3dNS;
	}, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
	
	if (xml3d && xml3d.update)
		this.updateElement = xml3d;

};

org.xml3d.animation.XML3DAnimationManager.prototype.init = function() {
	var ois = document.getElementsByTagNameNS(org.xml3d.x3dNS, 'OrientationInterpolator');
	for(var i = 0; i < ois.length; i++)
	{
		if (ois[i].hasAttribute('id'))
		{
			this.interpolators[ois[i].getAttribute('id')] = new org.xml3d.animation.X3DOrientationInterpolation(ois[i]);
		}
	}
	var ois = document.getElementsByTagNameNS(org.xml3d.x3dNS, 'PositionInterpolator');
	for(var i = 0; i < ois.length; i++)
	{
		if (ois[i].hasAttribute('id'))
		{
			this.interpolators[ois[i].getAttribute('id')] = new org.xml3d.animation.X3DPositionInterpolation(ois[i]);
		}
	}
	var a = this;
	window.setInterval(function() { a.progress(); }, 30);
};

org.xml3d.animation.XML3DAnimationManager.prototype.updateInterpolators = function() {
	var ois = document.getElementsByTagNameNS(org.xml3d.x3dNS, 'OrientationInterpolator');
	for(var i = 0; i < ois.length; i++)
	{
		if (ois[i].hasAttribute('id'))
		{
			if (this.interpolators[ois[i].getAttribute('id')] == undefined)
				this.interpolators[ois[i].getAttribute('id')] = new org.xml3d.animation.X3DOrientationInterpolation(ois[i]);
		}
	}
	var ois = document.getElementsByTagNameNS(org.xml3d.x3dNS, 'PositionInterpolator');
	for(var i = 0; i < ois.length; i++)
	{
		if (ois[i].hasAttribute('id'))
		{
			if (this.interpolators[ois[i].getAttribute('id')] == undefined)
			this.interpolators[ois[i].getAttribute('id')] = new org.xml3d.animation.X3DPositionInterpolation(ois[i]);
		}
	}
};

org.xml3d.animation.XML3DAnimationManager.prototype.startAnimation = function(aniID, transID, transAttr, duration, loop) {
	
	if (duration === undefined)
		duration = 3000;
	
	if (loop === undefined)
		loop = false;
	
	if(this.interpolators[aniID] === undefined)
	{
		org.xml3d.debug.logWarning("Unknown Interpolator: " + aniID);
		return;
	}
	var interpolator = this.interpolators[aniID];
	if (!interpolator.isValid())
	{
		org.xml3d.debug.logWarning("Could not initialize Interpolator: " + aniID);
		return;
	}
	var trans = document.getElementById(transID);
	if (!trans)
	{
		org.xml3d.debug.logWarning("Could not find animation target: " + transID);
		return;
	}
	
	var field = trans.getAttributeNode(transAttr);
	if (!field)
	{
		field = document.createAttribute(transAttr);
		field.nodeValue = "";
		trans.setAttributeNode(field);
	}
	
	if(interpolator.animations[field] !== undefined) {
		if (interpolator.animations[field].running)
		{
			org.xml3d.debug.logWarning("Animation already running");
		}
		else
		{
			// We start from the beginning when animation is restarted
			interpolator.animations[field].duration = duration;
			interpolator.animations[field].loop = loop;
			interpolator.animations[field].startTime = (new Date()).getTime();
			interpolator.animations[field].running = true;
		}
		return interpolator.animations[field];
	}
	
	interpolator.animations[field] = {};
	interpolator.animations[field].field = field;
	interpolator.animations[field].node = trans;
	interpolator.animations[field].attribute = transAttr;
	interpolator.animations[field].duration = duration;
	interpolator.animations[field].loop = loop;
	interpolator.animations[field].startTime = (new Date()).getTime();
	interpolator.animations[field].running = true;
	
	return interpolator.animations[field];
};<commit_msg>webgl animation: improved updating of manager and interpolators at run time<commit_after>//Check, if basics have already been defined
var org;
if (!org || !org.xml3d)
  throw new Error("xml3d.js has to be included first");

//Create global symbol org.xml3d.animation
if (!org.xml3d.animation)
	org.xml3d.animation = {};
else if (typeof org.xml3d.animation != "object")
	throw new Error("org.xml3d.animation already exists and is not an object");

// This is quirk required  to run animation manager initalization only after full
// document is loaded and all X3D interpolation elements are accesible.

// Browsers  based  on  Gecko 1.9.2 (e.g. Firefox 3.5) will only execute function
// that is set to timeout in 0 milliseconds exactly after document will be loaded
// or  as  soon  as  possible  if  document is already loaded, thus we can safely
// initalize animation manager. Such browsers can  be checked by testing value of
// document.readyState, which must be undefined.

// Other browsers may execute function  even  before loading  of  the webpage  is 
// finished, but they define document.readyState,  which allows us to detech such
// state  and  register event handler, which  will  run  the  initalization after 
// document is fully loaded.

setTimeout(function() {
	function initAnimationManager() {
		org.xml3d.debug.logInfo("Initializing Animation Manager.");
		org.xml3d.animation.animationManager = new org.xml3d.animation.XML3DAnimationManager();
		org.xml3d.animation.animationManager.init();
	};
	
	if (document.readyState == "complete" || // All major browsers except Gecko 1.9.2 or earlier.
		document.readyState == undefined) // Gecko 1.9.2 or earlier version. Document is guaranteed to be loaded when running this code.
		initAnimationManager();
	else
		window.addEventListener('load', initAnimationManager, false);
}, 0);

org.xml3d.startAnimation = function(aniID, transID, transAttr, duration, loop)
{
	return org.xml3d.animation.animationManager.startAnimation(aniID, transID, transAttr, duration, loop);
};

org.xml3d.stopAnimation = function(handle)
{
	org.xml3d.animation.animationManager.stopAnimation(handle);
};

org.xml3d.stopAllAnimations = function() 
{
	org.xml3d.animation.animationManager.stopAllAnimations();
};

org.xml3d.animation.XML3DAnimationManager = function() {
	this.interpolators = {};
	var xml3d = document.evaluate('//xml3d:xml3d', document, function() {
		return org.xml3d.xml3dNS;
	}, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
	
	if (xml3d && xml3d.update)
		this.updateElement = xml3d;
};

org.xml3d.animation.XML3DAnimationManager.prototype.init = function() {
	
	this.updateInterpolators();

	var a = this;
	
	window.addEventListener("DOMNodeInserted", 
		function(evt) { a.onNodeInserted(evt); });	
	window.addEventListener("DOMNodeRemoved", 
		function(evt) { a.onNodeRemoved(evt); });
		
	window.setInterval(function() { a.progress(); }, 30);
};

org.xml3d.animation.XML3DAnimationManager.prototype.addInterpolator = function(pol) {

	var cons = null; 
	if(pol.localName === 'OrientationInterpolator')
		cons = org.xml3d.animation.X3DOrientationInterpolation; 
	else if(pol.localName === 'PositionInterpolator')
		cons = org.xml3d.animation.X3DPositionInterpolation;
	else
		return; // don't support others
	
	if (pol.hasAttribute('id'))
	{
		if (this.interpolators[pol.getAttribute('id')] == undefined)
		{
			this.interpolators[pol.getAttribute('id')] = new cons(pol);
		}
	}
}; 

org.xml3d.animation.XML3DAnimationManager.prototype.onNodeInserted = function(evt) { 
	
	if(evt.target.namespaceURI !== org.xml3d.x3dNS)
		return; 
	
	this.addInterpolator(evt.target); 
};

org.xml3d.animation.XML3DAnimationManager.prototype.onNodeRemoved = function(evt) { 
	
	var t = evt.target;
	if(t.namespaceURI !== org.xml3d.x3dNS)
		return; 
	
	if(t.localName !== 'OrientationInterpolator' 
	&& t.localName !== 'PositionInterpolator')	 
		return; 
	
	if(t.hasAttribute('id'))
	{
		if(this.interpolators[t.getAttribute('id')])
			this.interpolators[t.getAttribute('id')] = undefined; 
	}
}; 



org.xml3d.animation.XML3DAnimationManager.prototype.updateInterpolators = function() {
	var ois = document.getElementsByTagNameNS(org.xml3d.x3dNS, 'OrientationInterpolator');
	for(var i = 0; i < ois.length; i++)
	{
		this.addInterpolator(ois[i]); 
	}
	
	var ois = document.getElementsByTagNameNS(org.xml3d.x3dNS, 'PositionInterpolator');
	for(var i = 0; i < ois.length; i++)
	{
		this.addInterpolator(ois[i]); 
	}
};

org.xml3d.animation.XML3DAnimationManager.prototype.startAnimation = function(aniID, transID, transAttr, duration, loop) {
	
	if (duration === undefined)
		duration = 3000;
	
	if (loop === undefined)
		loop = false;
	
	if(this.interpolators[aniID] === undefined)
	{
		org.xml3d.debug.logWarning("Unknown Interpolator: " + aniID);
		return;
	}
	var interpolator = this.interpolators[aniID];
	if (!interpolator.isValid())
	{
		org.xml3d.debug.logWarning("Could not initialize Interpolator: " + aniID);
		return;
	}
	var trans = document.getElementById(transID);
	if (!trans)
	{
		org.xml3d.debug.logWarning("Could not find animation target: " + transID);
		return;
	}
	
	var field = trans.getAttributeNode(transAttr);
	if (!field)
	{
		field = document.createAttribute(transAttr);
		field.nodeValue = "";
		trans.setAttributeNode(field);
	}
	
	// force interpolator to re-read it's attributes in case they changed 
	interpolator.isInit = false; 
	
	if(interpolator.animations[field] !== undefined) {
		if (interpolator.animations[field].running)
		{
			org.xml3d.debug.logWarning("Animation already running");
		}
		else
		{
			// We start from the beginning when animation is restarted
			interpolator.animations[field].duration = duration;
			interpolator.animations[field].loop = loop;
			interpolator.animations[field].startTime = (new Date()).getTime();
			interpolator.animations[field].running = true;
		}
		return interpolator.animations[field];
	}
	
	interpolator.animations[field] = {};
	interpolator.animations[field].field = field;
	interpolator.animations[field].node = trans;
	interpolator.animations[field].attribute = transAttr;
	interpolator.animations[field].duration = duration;
	interpolator.animations[field].loop = loop;
	interpolator.animations[field].startTime = (new Date()).getTime();
	interpolator.animations[field].running = true;
	
	return interpolator.animations[field];
};
{'fraction_non_alphanumeric': 0.1300779647107099, 'fraction_numerical': 0.012802626179729175, 'mean_word_length': 4.731890874882408, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 83}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5254440', 'n_tokens_mistral': 4224, 'n_tokens_neox': 3986, 'n_words': 863}