<?xml version="1.0" encoding="WIN-1251"?>
<rmml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="R:\collaborative-nir\program\Cscl3DWS\rmml\RMML.xsd">
	<include src="rmcomscr:equip.xml"/>
	<include src="rmcomscr:dragcomp.xml"/>
	<!--
	Класс одной пробирки, находящейся в ячейке таблицы
	-->
	<group _name="ceLiqTableProbirka" _class="ceProbirka">
		<script>
                this.resPath = getFullPath("/resources/liqtable/TestTube/");
				this.autoPourTime = 1000;
        </script>
		<object _name="obj" src="/resources/liqtable/TestTube/Model/mesh.cfg"  enabled="false">
			<motion _name="mtMove" src="/resources/liqtable/TestTube/locations/mtMove.caf"/>
			<motion _name="mtSet1" src="/resources/liqtable/TestTube/locations/mtDestFront.caf"/>
			<motion _name="mtSet10" src="/resources/liqtable/TestTube/locations/mtDestSource.caf"/>
			<motion _name="mtSet11" src="/resources/liqtable/TestTube/locations/mtDestSource2.caf"/>
			<motion _name="mtSet12" src="/resources/liqtable/TestTube/locations/mtDestSource3.caf"/>
		</object>
		<script>
			this.mEventHandler = null;
			this.maProperties = new Array();
			// Инициализация
			var sx = 0;
			var sy = 70;
			var sz = 5;
			this.shiftKeyPos( this.obj.mtSet1, 0, sx, sy, sz);
			this.shiftKeyPos( this.obj.mtSet10, 0, sx, sy, sz+0);
			this.shiftKeyPos( this.obj.mtSet11, 0, sx, sy, sz+1);
			this.shiftKeyPos( this.obj.mtSet12, 0, sx, sy, sz+1);
			// Меняем движения на переливание
			this.pourFirstID = 10;
			this.pourStartID = 11;
			this.pourEndID = 12;
		</script>

		<script><![CDATA[
			this.sBaseProperties = "";
			function setBaseProperties(str)
			{
				this.sBaseProperties = str;
				this.maProperties.length = 0;
				var props = str.split(";");
				for( var i=0; i<props.length; i++)
				{
					var property = props[i].split("=");
					if( property.length!=2)
					{
						trace("#E00000 liqTable error: incorrect property["+props[i]+"]");
						continue;
					}
					var pname = property[0];
					var pval = property[1];
					if( pname == "r")
						this.maProperties.push( new Array("r", Number(pval)));
					else	if( pname == "g")
						this.maProperties.push( new Array("g", Number(pval)));
					else	if( pname == "b")
						this.maProperties.push( new Array("b", Number(pval)));
					else	if( pname == "a")
						this.maProperties.push( new Array("a", Number(pval)));
					else	if( pname == "aback")
						this.maProperties.push( new Array("aback", Number(pval)));
					else	if( pname == "substlevel")
						this.maProperties.push( new Array("substlevel", Number(pval)));
					else	if( pname == "substmap")
						this.maProperties.push( new Array("substmap", pval));
					else	if( pname == "map")
						this.maProperties.push( new Array("map", pval));
					else	if( pname == "mapanim")
						this.maProperties.push( new Array("mapanim", pval));
					else	if( pname == "v_intensity")
						this.maProperties.push( new Array("v_intensity", Number(pval)));
					else	if( pname == "v_velocity")
						this.maProperties.push( new Array("v_velocity", Number(pval)));
					else	if( pname == "v_wtoler")
						this.maProperties.push( new Array("v_wtoler", Number(pval)));
					else	if( pname == "v_growps")
						this.maProperties.push( new Array("v_growps", Number(pval)));
					else	if( pname == "v_startsize")
						this.maProperties.push( new Array("v_startsize", Number(pval)));
					else	if( pname == "amap")
						this.maProperties.push( new Array("amap", Number(pval)));
					else	if( pname == "mapr")
						this.maProperties.push( new Array("mapr", Number(pval)));
					else	if( pname == "mapg")
						this.maProperties.push( new Array("mapg", Number(pval)));
					else	if( pname == "mapb")
						this.maProperties.push( new Array("mapb", Number(pval)));
					else	if( pname == "time")
						this.maProperties.push( new Array("time", Number(pval)));
					else
					{
						trace("#E00000 liqTable error: invalid property["+pname+"]");
					}
				}
				this.restoreBaseProperties();
			}

			function restoreBaseProperties()
			{
				var level = this.obj.level;
				setDefaultLiquidParams();
				this.obj.level = level;
				setPropertiesFromArray(maProperties);
			}

			function getPropertyValue(sProperty)
			{
				for( var i=0; i<maProperties.length; i++)
				{
					var property = maProperties[i];
					if( property[0] == sProperty)
						return property[1];
				}
				return null;
			}

			function setPropertiesFromArray(aProperties)
			{
				for( var i=0; i<aProperties.length; i++)
				{
					var property = aProperties[i];
					var pname = property[0];
					var pval = property[1];
					if( pname == "r")
						this.obj.r = pval;
					else	if( pname == "g")
						this.obj.g = pval;
					else	if( pname == "b")
						this.obj.b = pval;
					else	if( pname == "a")
						this.obj.a = pval;
					else	if( pname == "aback")
						this.obj.aback = pval;
					else	if( pname == "substlevel")
						this.obj.substlevel = pval;
					else	if( pname == "substmap")
						this.obj.substmap = pval;
					else	if( pname == "v_intensity")
						this.obj.v_intensity = pval;
					else	if( pname == "v_velocity")
						this.obj.v_velocity = pval;
					else	if( pname == "v_wtoler")
						this.obj.v_wtoler = pval;
					else	if( pname == "v_growps")
						this.obj.v_growps = pval;
					else	if( pname == "v_startsize")
						this.obj.v_startsize = pval;
					else	if( pname == "mapr")
						this.obj.mapr = pval;
					else	if( pname == "mapg")
						this.obj.mapg = pval;
					else	if( pname == "mapb")
						this.obj.mapb = pval;
					else	if( pname == "amap")
						this.obj.amap = pval;
					else	if( pname == "map")
						this.obj.map = pval;
					else	if( pname == "mapanim")
						this.obj.mapanim = eval(pval);
				}
			}

			function initialize(x,y,z)
			{
				this.obj.position = new Position3D(x,y,z);
				this.obj.rotation = this.obj.mtMove.tracks[-1].frames[0]._rotation;
				this.setPosition3D(x, y, z);
			}

			function setPosition3D(x, y, z)
			{
				this.obj.mtMove.tracks[-1].frames[0]._pos = new Position3D(x, y, z);
				this.moveTo( "mtMove", 0);
			}

			function movePosition3D(x, y, z, time)
			{
				this.obj.mtMove.tracks[-1].frames[0]._pos = new Position3D(x, y, z);
				return this.moveTo( "mtMove", time);
			}

			function level_done()
			{
				if( this.mEventHandler != null)
				{
					if( typeof(this.mEventHandler.onLevelDone) == "function")
					{
						this.mEventHandler.onLevelDone( );
					}
					else
					{
						trace("#E00000 liqTable error: onLevelDone is not a function");
					}
				}
			}

			function onFirstDrop()
			{
				if( typeof(this.mEventHandler.onFirstDrop) == "function")
				{
					this.mEventHandler.onFirstDrop( );
				}
				else
				{
					trace("#E00000 liqTable error: onFirstDrop is not a function");
				}
			}
		]]></script>
	</group>

	<!--
	Место для ответа
	-->
	<composition name="CAnswerPlace">
		<composition   _name="subst" _class="CResizablePaper" _depth="1" visible="false">
			<image _name="lt" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(0,0,2,2);</script></image>
			<image _name="ct" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(1,0,2,2);</script></image>
			<image _name="rt" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(2,0,2,2);</script></image>
			<image _name="lc" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(0,1,2,2);</script></image>
			<image _name="cc" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(1,1,2,2);</script></image>
			<image _name="rc" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(2,1,2,2);</script></image>
			<image _name="lb" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(0,2,2,2);</script></image>
			<image _name="cb" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(1,2,2,2);</script></image>
			<image _name="rb" src="/resources/liqtable/imAnswerPlace.png"><script>this.crop(2,2,2,2);</script></image>
		</composition>
		<image name="imQuest" src="/resources/liqtable/imQuestion.png"/>
		<text _name="txt" visible="false"/>

		<script>
			this.onScreenWidth = 100;
			this.onScreenHeight = 100;
			this.mMirror = null;	// визуальная копия

			function setType( sType)
			{
				if( sType == "text")
					this.txt.style = parent.stlAnswer;
				else	if( sType == "formula")
					this.txt.style = parent.stlEquation;
				else
				{
					trace("#E00000 liqTable error: wrong answer type");
				}
			}
			function resize(w,h)
			{
				this.subst.resize(w, h);
				imQuest.x = (w-imQuest.getMediaSize().width)/2;
				imQuest.y = (h-imQuest.getMediaSize().height)/2;
				this.onScreenWidth = w;
				this.onScreenHeight = h;
			}

			function highlight(val)
			{
				this.subst.visible = val;
			}

			function isHighlighted()
			{
				return this.subst.visible;
			}

			function setText(aText)
			{
				if( aText != null)
				{
					var sText = aText;
					var sType = "text";
					if( aText.indexOf(":")!=-1)
					{
						var ar = aText.split(":");
						sText = ar[0];
						sType = ar[1];
					}
					this.txt.value = sText;
					this.setType( sType);
					imQuest.visible = false;
					this.txt.x = this.onScreenWidth/2 - this.txt.width/2;
					this.txt.y = this.onScreenHeight/2 - this.txt.height/2;
				}
				else
					imQuest.visible = true;
				this.txt.visible = !imQuest.visible;
				if( this.mMirror!=null)
					this.mMirror.setText( aText);
			}

			function setMirror( aMirror)
			{
				this.mMirror = aMirror;
			}
			function getTextValue()
			{
				if( !txt.visible)	return "";
				return this.txt.value;
			}
		</script>
	</composition>

	<!--
	Ответ
	-->
	<composition name="CDragAnswer" class="CDraggableComposition"  enabled="false">
		<text _name="txt" style="_parent_parent.stlAnswer"/>

		<script>
			// Переменные
			this.correctID = 0;
			this.locationID = -1;
			this.mRealText = "";

			this.addHotspot( this.txt);
			function setText(atxt)
			{
				txt.value = atxt;
			}
			function setRealText( aText)
			{
				mRealText = aText;
			}
			function acceptMoveBy(dx, dy)
			{
				return this.parent.acceptMoveBy( this, dx, dy);
			}
			function beginDrag()
			{
				this.parent.BeginDrag( this);
			}
			function setStyle( aStyle)
			{
				this.txt.style = aStyle;
			}
		</script>
	</composition>

	<composition name="CAnswer">
		<styles _name="stlAnswer" fontSize="18"  fontFamily="Microsoft Sans Serif"  textAlign="left" color="#000000"/>
		<text _name="txt" style="parent.stlAnswer"/>
		<script>
			this.myDrag = new Composition();
			this.myDrag._class = "CDragAnswer";
			this.myDrag.visible = false;
			this.myDrag.parent = this.parent;
			this.myDrag.x = this.x;
			this.myDrag.y = this.y;

			function setPosition(ax,ay)
			{
				this.x = ax;		this.y = ay;
				this.myDrag.x = ax;	this.myDrag.y = ay;
			}
			function setText(aText)
			{
				var sText = aText;
				var sType = "text";
				if( aText.indexOf(":")!=-1)
				{
					var ar = aText.split(":");
					sText = ar[0];
					sType = ar[1];
				}
				txt.value = sText;
				this.setType( sType);
				this.myDrag.setText(sText);
				this.myDrag.setRealText(aText);
			}
			function getWidth()
			{
				return txt.getMediaSize().width;
			}
			function setCorrectID( aCorrectID)
			{
				this.myDrag.correctID = aCorrectID;
			}
			function setType( sType)
			{
				if( sType == "text")
					this.txt.style = parent.stlAnswer;
				else	if( sType == "formula")
					this.txt.style = parent.stlEquation;
				else
				{
					trace("#E00000 liqTable error: wrong answer type");
					return;
				}
				if( this.myDrag != null)
				{
					this.myDrag.setStyle(this.txt.style);
				}
			}
			function getTextValue()
			{
				return this.txt.value;
			}
			function getRealTextValue()
			{
				return this.myDrag.mRealText;
			}
			function getCorrectID( )
			{
				return this.myDrag.correctID;
			}
			function getLocationID( )
			{
				return this.myDrag.locationID;
			}
		</script>
		<script event="onPress">
			this.setPosition( this.x, this.y);
			this.myDrag.stick( true);
			this.myDrag.visible = true;
		</script>
	</composition>

	<!--
	Таблица с пробирками
	-->
	<composition name="CPourTable">
		<script>
			// Параметры таблицы
				// задаются пользователем
			this.mScene3D = null;
			this.mViewport = null;
			this.maInitParam = null;
			this.maAnswers = null;
			this.maVAnswers = null;
			this.sDisabledSrc = "/resources/liqtable/bgDisabled.png";
			this.mDefaultScale = new Scale3D(1,1,1);
			this.mAnswersPlacesDX = 0;
			this.mAnswersPlacesDY = 0;
				// рассчитываются
			this.mHCellsCount = 0;	// количество ячеек по горизонтали
			this.mVCellsCount = 0;	// количество ячеек по вертикали
				// параметры объектов
			this.startLevel = 40;

			// Динамические объекты
			this.aAnswers = new Array();
			this.aAnswersPlaces = new Array();

			// Параметры реакции
			this.mSource = null;
			this.mDest = null;
			this.mResult = null;

			// Перетаскивание
			this.mDragItem = null;
		</script>

		<audio	name="audOnce"/>
		<audio	name="audHelp"/>
		<sequencer name="seqSounds">
			<script>
				1000;
			</script>
			<script>
				this.audOnce.rewindAndPlay();
				"audOnce.onPlayed";
			</script>
			<script>
				this.audHelp.rewindAndPlay();
				"audHelp.onPlayed";
			</script>
			<script>
				60000;
			</script>
			<script>
				this.seqSounds.currentFrame = 2;
			</script>
		</sequencer>

		<styles _name="stlAnswer" fontSize="18"  fontFamily="Microsoft Sans Serif"  textAlign="left" color="#975525"/>
		<styles _name="stlEquation" fontSize="22"  fontFamily="Microsoft Sans Serif"  textAlign="left" color="#00639E"/>

		<script><![CDATA[
			function setSounds(pathOnce, pathHelp)
			{
				this.audOnce.src = pathOnce;
				this.audHelp.src = pathHelp;
				this.seqSounds.rewindAndPlay();
			}

			function stopHelp()
			{
				this.seqSounds.stop();
				this.audOnce.stop();
				this.audHelp.stop();
			}

			function Build()
			{
				if( mScene3D == null)
				{
					trace("#E00000 liqTable error: mScene3D==null");
					return;
				}
				if( mViewport == null)
				{
					trace("#E00000 liqTable error: mViewport==null");
					return;
				}
				if( mViewport.camera == null)
				{
					trace("#E00000 liqTable error: mViewport.camera==null");
					return;
				}
				if( mViewport.width==0 || mViewport.height==0)
				{
					trace("#E00000 liqTable error: viewport size is wrong");
					return;
				}
				if( maInitParam == null)
				{
					trace("#E00000 liqTable error: maInitParam==null");
					return;
				}
				if( !(maInitParam instanceof Array))
				{
					trace("#E00000 liqTable error: maInitParam in not an Array");
					return;
				}
				if( maAnswers == null)
				{
					trace("#E00000 liqTable error: maAnswers==null");
					return;
				}
				if( !(maAnswers instanceof Array))
				{
					trace("#E00000 liqTable error: maAnswers in not an Array");
					return;
				}
				if( this.mDefaultScale.x<=0 || this.mDefaultScale.y<=0 || this.mDefaultScale.z<=0)
				{
					trace("#E00000 liqTable error: incorrect mDefaultScale");
					return;
				}
				this.mVCellsCount = maInitParam.length;
				var camPos = this.mViewport.camera.position;
				this.mViewport.camera.position = new Position3D(camPos.x / this.mDefaultScale.x,
																camPos.y / this.mDefaultScale.y,
																camPos.z / this.mDefaultScale.z);
				for( var i=0; i<this.mVCellsCount; i++)
				{
					var aLine = maInitParam[i];
					if( !(aLine instanceof Array))
					{
						trace("#E00000 liqTable error: aLine["+i+"] in not an Array");
						return;
					}
					if( this.mHCellsCount == 0)
					{
						this.mHCellsCount = aLine.length;
					}
					else
					{
						if( this.mHCellsCount != aLine.length)
						{
							trace("#E00000 liqTable error: this.mVCellsCount != aLine.length[ i="+i+", j="+j+"]");
							return;
						}
					}
					for( var j=0; j<this.mHCellsCount; j++)
					{
						if(j==0 && i==0)
						{
							continue;
						}
						if(j==i && maVAnswers==null)
						{
							var bgDisabled = new Image();
							bgDisabled.src = this.sDisabledSrc;
							bgDisabled.x = this.getScreenCellX(j)+3;
							bgDisabled.y = this.getScreenCellY(i)+4;
							bgDisabled.parent = this;
							continue;
						}
						// создаем место для размещения ответа
						if( i==0)
						{
							var answerPlace = new Composition();
							answerPlace.name = "answer_h"+j;
							answerPlace._class = "CAnswerPlace";
							if( mHCellsCount == 5)
							{
								answerPlace.x = this.getScreenCellX(j)+2;
								answerPlace.y = this.mViewport.y-43;
							}
							else	if( mHCellsCount == 6)
							{
								answerPlace.x = this.getScreenCellX(j)+1;
								answerPlace.y = this.mViewport.y-37;
							}
							else
							{
								answerPlace.x = this.getScreenCellX(j);
								answerPlace.y = this.mViewport.y-40;
							}
							answerPlace.parent = this;

							answerPlace.resize(getScreenCellWidth(), 30);
							aAnswersPlaces.push(answerPlace);
						}
						var	params = aLine[j];
						var	object = CreateProb(i, j);
						object.setBaseProperties(aLine[j]);
						/*if( i!=0 && j!=0)
						{
							object.obj.visible = false;
						}*/
						object.obj.visible = false;

						if( i!=0 && j!=0)
						{
							var hotspot = CreateHotspot( i, j);
							//??
						}
					}
					// Вертикальные ответы
					if( i!=0)
					{
						var answerPlace = new Composition();
						answerPlace.name = "answer_v"+i;
						answerPlace._class = "CAnswerPlace";
						answerPlace.parent = this;
						answerPlace.x = this.getScreenCellX(0) - answerPlace.onScreenWidth - 57;
						answerPlace.y = this.getScreenCellY(i);

						answerPlace.resize(getScreenCellWidth(), getScreenCellHeight());
						if( maVAnswers != null)
						{
							if( maVAnswers.length >= i)
							{
								answerPlace.setText( maVAnswers[i-1]);
							}
						}
						else
						{
							var hAnswer = eval("this.answer_h"+i);
							hAnswer.setMirror( answerPlace);
						}
					}
				}

				// Создаем варианты ответа
				for( var i=0; i<this.maAnswers.length; i++)
				{
					var sText = maAnswers[i];
					var sType = "text";
					if( sText.indexOf(":")==-1)
					{
						trace("#E00000 liqTable error: answer don`t contains correct index["+sText+"]");
						continue;
					}

					var answer = new Composition();
					answer._class = "CAnswer";
					answer.parent = this;

					var ar = sText.split(":");
					answer.setText( ar[0]);
					answer.setCorrectID( Number(ar[1]));

					var answersCorner = scene.getAnswersTopLeft();
					answer.setPosition(answersCorner.x + getAnswerX( answer) - this.x,
										answersCorner.y - this.y - 15/*answer.height/2*/);

					aAnswers.push( answer);
				}

				this.seqShowAll.rewindAndPlay();
			}

			function getAnswerX(answer)
			{
				var ax = 0;
				for( var i=0; i<aAnswers.length; i++)
				{
					if( aAnswers[i] == answer)
					{
						break;
					}
					ax += aAnswers[i].getWidth() + 40;
				}
				return ax;
			}

			function getScreenCellWidth()
			{
				return this.mViewport.width/this.mHCellsCount;
			}

			function getScreenCellHeight()
			{
				return this.mViewport.height/this.mVCellsCount;
			}

			function getScreenCellX(cell)
			{
				return this.mViewport.x + getScreenCellWidth()*cell;
			}

			function getScreenCellY(cell)
			{
				return this.mViewport.y + getScreenCellHeight()*cell;
			}

			function getObjectPosition( i, j)
			{
				var alpha = (this.mViewport.camera.fov*3.14/180)/2;
				var sideSize = -this.mViewport.camera.position.y*Math.tan( alpha);
				var sizePerHCell = 2*sideSize/this.mHCellsCount;
				var sizePerVCell = 2*sideSize/this.mVCellsCount;
				var hK = this.mViewport.height/this.mViewport.width;

				return new Position3D(-sideSize+sizePerHCell*(j+0.5), 0, (sideSize-sizePerVCell*(i+0.9))*hK);
			}

			function CreateProb(i, j)
			{
				var obj = new Group();
				obj._class = "ceLiqTableProbirka";
				obj.name = "prob"+i+"_"+j;
				obj.parent = this.mScene3D;

				obj.cellX = j;
				obj.cellY = i;

				var objPosition = getObjectPosition( i, j);
				obj.initialize(objPosition.x, objPosition.y, objPosition.z);
				obj.mEventHandler = this;
				obj.obj.level = this.startLevel;
				//obj.obj.scale = new Scale3D( this.mDefaultScale.x, this.mDefaultScale.y, this.mDefaultScale.z);
				return obj;
			}

			function CreateHotspot(i, j)
			{
				var hotspot = new Button();
				hotspot.x = getScreenCellX(j);
				hotspot.y = getScreenCellY(i);
				hotspot.width = getScreenCellWidth();
				hotspot.height = getScreenCellHeight();
				hotspot.depth = 10;
				hotspot.parent = this;
				hotspot.cellX = j;
				hotspot.done = false;
				hotspot.cellY = i;
				hotspot.name = "btn"+i+"_"+j;
				hotspot.onPress = function()
				{
					this.done = true;
					this.enabled = false;
					if( this.parent.InitPouring(hotspot.cellY, hotspot.cellX))
					{
						BeginPour();
					}
				}
				return hotspot;
			}

			function GetHotspot(i, j)
			{
				return eval("this.btn"+i+"_"+j);
			}

			// Устанавливает параметры смешивания
			function InitPouring(i, j)
			{
				trace("showPouring["+i+","+j+"]");
				var source = eval("scene."+this.mScene3D.name+".prob"+i+"_0");
				if( typeof(source)=="undefined" || source==null)
				{
					trace("#E00000 liqTable error: source is undefined[i="+i+",j=0]");
					return;
				}
				var dest = eval("scene."+this.mScene3D.name+".prob0_"+j);
				if( typeof(dest)=="undefined" || dest==null)
				{
					trace("#E00000 liqTable error: dest is undefined[i=0,"+j+"]");
					return;
				}
				var res = eval("scene."+this.mScene3D.name+".prob"+i+"_"+j);
				if( typeof(res)=="undefined" || res==null)
				{
					trace("#E00000 liqTable error: res is undefined[i="+i+",j="+j+"]");
					return;
				}
				trace("source.name="+source.name);
				trace("dest.name="+dest.name);
				trace("res.name="+res.name);
				//
				this.mSource = source;
				this.mDest = dest;
				this.mResult = res;

				return true;
			}

			// Начинает движение пробирок и реакцию
			function BeginPour()
			{
				if( mSource==null)
				{
					trace("#E00000 liqTable error: mSource == null");
					return;
				}
				if( mDest==null)
				{
					trace("#E00000 liqTable error: mDest == null");
					return;
				}
				if( mResult==null)
				{
					trace("#E00000 liqTable error: mResult == null");
					return;
				}
				// Начинаем движение
				mDest.moveTo(1, 1000);
				mSource.startPour( mDest, this.startLevel, this.startLevel*1.8);
				this.DisableAll();
			}

			// Начало реакции
			function onFirstDrop()
			{
				if( typeof(scene.handleReaction)!="function" ||
					!scene.handleReaction( mResult.cellY, mResult.cellX, mDest))
				{
					this.handleDefaultReaction();
				}
			}

			// Конец реакции
			function onLevelDone()
			{
				this.mSource.obj.level = 0;
				this.seqDone.rewindAndPlay();
			}

			// Реакция по умолчанию
			function handleDefaultReaction()
			{
				var	bDissolve = false;
				var	bSediment = false;
				for( var i=0; i<mResult.maProperties.length; i++)
				{
					var property = mResult.maProperties[i];
					// Должен появиться осадок
					if( property[0] == "substlevel")
					{
						bSediment = true;
					}
				}

				if( !bSediment)
				{
					// но если осадка нет, а в пробирке Dest есть осадок - то это растворение
					if( mDest.obj.substlevel!=0)
					{
						bDissolve = true;
					}
				}

				// Проведем реакцию
				if( bDissolve)
				{
				}
				else	if( bSediment)
				{
					trace("#0000E0 Sediment reaction...");
					if(mDest.animSediment == null)
						mDest.animSediment = scene.loadReacAnimation("sediment");

					mDest.obj.asubst = 0;
					mDest.obj.substlevel = 0;
					mDest.obj.blendtime = 1000;

					mDest.beginChanges();
						mDest.setPropertiesFromArray( mResult.maProperties);
						mDest.obj.amap = 255;
						mDest.obj.asubst = 255;
						mDest.obj.mapanim = mDest.animSediment;
					mDest.endChanges();

					mDest.blendnolevel(1000);
					mDest.animSediment.rewindAndPlay() ;
				}
				else
				{
					mDest.snapshot();
					mDest.setPropertiesFromArray( mResult.maProperties);
					mDest.blendnolevel( 1000);
				}
			}

			// Перетаскивание ответов
			this.activeAnswerPlace = null;
			function acceptMoveBy( obj, dx, dy)
			{
				var ret = new Object;
				ret.x = dx;
				ret.y = dy;
				// Проверим на близость с какому либо ответу
				var i=0;
				for( ; i<this.aAnswersPlaces.length; i++)
				{
					var place = this.aAnswersPlaces[i];
					var destCenterX = place.x + place.onScreenWidth/2;
					var destCenterY = place.y + place.onScreenHeight/2;
					var srcCenterX = obj.x + obj.width/2  + dx;
					var srcCenterY = obj.y + obj.height/2  + dy;
					if( Math.abs( srcCenterX-destCenterX) < obj.width/2 &&
						Math.abs( srcCenterY-destCenterY) < obj.height/2)
					{
						this.activeAnswerPlace = place;
						this.activeAnswerPlace.highlight( true);
						break;
					}
				}
				if( i == this.aAnswersPlaces.length && this.activeAnswerPlace!=null)
				{
					this.activeAnswerPlace.highlight( false);
				}
				return ret;
			}

			// Начало перетаскивания ответа
			function BeginDrag( aDragItem)
			{
				trace("BeginDrag aDragItem="+aDragItem);
				this.mDragItem = aDragItem;
			}

			// Показывает все правильные ответы
			function ShowCorrectAnswers()
			{
				trace("ShowCorrectAnswers="+this.aAnswers.length);
				for( var i=0; i<this.aAnswers.length; i++)
				{
					var answer = this.aAnswers[i];
					trace("answer.correctID="+answer.getCorrectID());
					if( answer.getCorrectID() < this.aAnswersPlaces.length)
					{
						trace("answer.getRealTextValue()="+answer.getRealTextValue());
						this.aAnswersPlaces[answer.getCorrectID()].setText( answer.getRealTextValue());
					}
					answer.myDrag.locationID = answer.getCorrectID();
				}
				for( var i=0; i<this.mVCellsCount; i++)
				{
					for( var j=0; j<this.mHCellsCount; j++)
					{
						var source = eval("scene."+this.mScene3D.name+".prob"+i+"_"+j);
						if( source!=null)
						{
							source.obj.visible=true;
							if( i!=0 && j!=0)
							{
								source.obj.level = this.startLevel*1.8;
							}
						}
						var hs = GetHotspot( i, j);
						if( hs != null)
						{
							hs.enabled = false;
							hs.done = true;
						}
					}
				}
				this.stopHelp();
			}

			// Показывает все правильные ответы
			function ShowAdvise()
			{
				var i=0;
				for( ; i<this.aAnswersPlaces.length; i++)
				{
					var j=0;
					for( ; j<this.aAnswers.length; j++)
					{
						var answer = this.aAnswers[j];
//trace(i+": answer.getLocationID()="+answer.getLocationID());
						var answer = this.aAnswers[j];
						if( answer.getCorrectID() == i && answer.getLocationID() == i)
						{
							break;
						}
					}
					if( j==this.aAnswers.length)
					{
						this.aAnswersPlaces[i].setText(null);
					}
				}
				this.stopHelp();
			}

			function EnableAll()
			{
				for( var i=0; i<this.mVCellsCount; i++)
				{
					for( var j=0; j<this.mHCellsCount; j++)
					{
						var hs = GetHotspot( i, j);
						if( hs!=null && !hs.done)
						{
							hs.enabled = true;
						}
					}
				}
			}

			function DisableAll()
			{
				for( var i=0; i<this.mVCellsCount; i++)
				{
					for( var j=0; j<this.mHCellsCount; j++)
					{
						var hs = GetHotspot( i, j);
						if( hs!=null)
						{
							hs.enabled = false;
						}
					}
				}
			}
		]]></script>

		<script event="onMouseUp"><![CDATA[
			trace("this.mDragItem="+this.mDragItem);
			if( this.mDragItem!=null)
			{
				this.mDragItem.stick( false);
				var i=0;
				for( ; i<this.aAnswersPlaces.length; i++)
				{
					var place = this.aAnswersPlaces[i];
					if( place.isHighlighted())
					{
						for( var j=0; j<this.aAnswers.length; j++)
						{
							var answer = this.aAnswers[j];
							if( answer.getLocationID() == i)
							{
								answer.myDrag.locationID = -1;
							}
						}
						place.highlight( false);
						place.setText(this.mDragItem.mRealText);
						this.mDragItem.x = place.x + place.onScreenWidth/2 - this.mDragItem.width/2;
						this.mDragItem.y = place.y + place.onScreenHeight/2 - this.mDragItem.height/2;
						this.mDragItem.locationID = i;
						break;
					}
				}
				this.mDragItem.visible = false;
				this.mDragItem = null;
			}
		]]></script>

		<sequencer name="seqShowAll">
			<script>
				500;
			</script>
			<script><![CDATA[
				for( var i=0; i<this.mVCellsCount; i++)
				{
					for( var j=0; j<this.mHCellsCount; j++)
					{
						var source = eval("scene."+this.mScene3D.name+".prob"+i+"_"+j);
						if( source!=null && (i==0 || j==0))
						{
							source.obj.visible=true;
						}
					}
				}
			]]></script>
		</sequencer>

		<sequencer name="seqDone">
			<script>
				var time = mResult.getPropertyValue("time");
				if( time==null)
					time = 1000;
				time;
			</script>
			<script>
				var moveTime = 1000;
				var resPosition = this.getObjectPosition( mResult.cellY, mResult.cellX);
				mDest.movePosition3D( resPosition.x, resPosition.y, resPosition.z, moveTime);

				var sourcePosition = this.getObjectPosition( mSource.cellY, mSource.cellX);
				mSource.movePosition3D( sourcePosition.x, sourcePosition.y, sourcePosition.z, moveTime);
				moveTime;
			</script>
			<script>
				// во что наливали
				mResult.obj.visible = true;
				mResult.obj.level = mDest.obj.level;
				// куда наливали
				mDest.restoreBaseProperties();
				mDest.obj.level = this.startLevel;
				mDest.obj.visible = false;
				// из чего наливали
				mSource.restoreBaseProperties();
				mSource.obj.level = this.startLevel;
				var destPosition = this.getObjectPosition( mDest.cellY, mResult.cellX);
				mDest.setPosition3D( destPosition.x, destPosition.y, destPosition.z);
			</script>
			<script>
				1000;
			</script>
			<script>
				mDest.obj.visible = true;
				this.EnableAll();
			</script>
		</sequencer>
	</composition>
</rmml>