void onAdaptiveControllerModelReady(params object[] args)
    {
#if UNITY_EDITOR
        if (Application.isPlaying)
        {
            return;
        }
#endif
        WaveVR_Controller.EDeviceType _device = (WaveVR_Controller.EDeviceType)args[0];

        if (this.deviceType == _device)
        {
            WaveVR_RenderModel wrm = this.GetComponentInChildren <WaveVR_RenderModel>();

            if (wrm != null)
            {
                GameObject modelObj = wrm.gameObject;

                int modelchild = modelObj.transform.childCount;
                PrintDebugLog("onAdaptiveControllerModelReady() model child: " + modelchild);
                for (int j = 0; j < modelchild; j++)
                {
                    GameObject childName = modelObj.transform.GetChild(j).gameObject;
                    if (childName.name == "__CM__Emitter" || childName.name == "_[CM]_Emitter")
                    {
                        emitter = childName;
                        PrintDebugLog("emitter local position (" + emitter.transform.localPosition.x + ", " + emitter.transform.localPosition.y + ", " + emitter.transform.localPosition.z + ")");
                        PrintDebugLog("emitter local EulerAngles " + emitter.transform.localEulerAngles);

                        if (moveToEmitter != null)
                        {
                            PrintDebugLog("__CM__Emitter is found, update objects' parent");

                            foreach (GameObject mgo in moveToEmitter)
                            {
                                if (mgo != null)
                                {
                                    PrintDebugLog("Move " + mgo.name + " to be children of emitter");
                                    mgo.transform.parent        = emitter.transform;
                                    mgo.transform.localRotation = Quaternion.identity;
                                    mgo.transform.localPosition = Vector3.zero;
                                    mgo.SetActive(false);
                                    mgo.SetActive(true);
                                }
                            }
                        }

                        break;
                    }
                }
            }
            else
            {
                PrintDebugLog("WaveVR_RenderModel is not found");
            }
        }
    }
	public void createIndicator() {
		if (!showIndicator) return;
		clearResourceAndObject();
		PrintDebugLog("create Indicator!");
		rw = WaveVR_Resource.instance;
		indicatorPrefab = Resources.Load("ComponentIndicator") as GameObject;

		if (indicatorPrefab == null)
		{
			PrintInfoLog("ComponentIndicator is not found!");
			return;
		}
		else
		{
			PrintDebugLog("ComponentIndicator is found!");
		}

		linePrefab = Resources.Load("LineIndicator") as GameObject;

		if (linePrefab == null)
		{
			PrintInfoLog("LineIndicator is not found!");
			return;
		}
		else
		{
			PrintDebugLog("LineIndicator is found!");
		}

		if (_HMD == null)
			_HMD = WaveVR_Render.Instance.gameObject;

		if (_HMD == null)
		{
			PrintInfoLog("Can't get HMD!");
			return;
		}

		var gc = transform.childCount;

		for (int i = 0; i < gc; i++)
		{
			GameObject go = transform.GetChild(i).gameObject;

			PrintInfoLog("child name is " + go.name);
		}

		PrintInfoLog("showIndicatorAngle: " + showIndicatorAngle + ", hideIndicatorByRoll: " + hideIndicatorByRoll + ", basedOnEmitter: " + basedOnEmitter);
		PrintInfoLog("Line settings--\n lineLength: " + lineLength + ", lineStartWidth: " + lineStartWidth + ", lineEndWidth: " + lineEndWidth + ", lineColor: " + lineColor);
		PrintInfoLog("Text settings--\n textCharacterSize: " + textCharacterSize + ", zhCharactarSize: " + zhCharactarSize + ", textFontSize: " + textFontSize + ", textColor: " + textColor);

		foreach (ButtonIndication bi in buttonIndicationList)
		{
			PrintInfoLog("keyType: " + bi.keyType + ", alignment: " + bi.alignment + ", offset: " + bi.indicationOffset + ", useMultiLanguage: " + bi.useMultiLanguage +
				", indication: " + bi.indicationText + ", followRotation: " + bi.followButtonRotation);

			// find component by name
			string partName = null;
			string partName1 = null;
			string partName2 = null;
			string indicationKey = null;
			switch(bi.keyType)
			{
				case ButtonIndication.KeyIndicator.Trigger:
					partName = "_[CM]_TriggerKey";
					partName1 = "__CM__TriggerKey";
					partName2 = "__CM__TriggerKey.__CM__TriggerKey";
					indicationKey = "TriggerKey";
					break;
				case ButtonIndication.KeyIndicator.TouchPad:
					partName = "_[CM]_TouchPad";
					partName1 = "__CM__TouchPad";
					partName2 = "__CM__TouchPad.__CM__TouchPad";
					indicationKey = "TouchPad";
					break;
				case ButtonIndication.KeyIndicator.Grip:
					partName = "_[CM]_Grip";
					partName1 = "__CM__Grip";
					partName2 = "__CM__Grip.__CM__Grip";
					indicationKey = "Grip";
					break;
				case ButtonIndication.KeyIndicator.DPad_Left:
					partName = "_[CM]_DPad_Left";
					partName1 = "__CM__DPad_Left";
					partName2 = "__CM__DPad_Left.__CM__DPad_Left";
					indicationKey = "DPad_Left";
					break;
				case ButtonIndication.KeyIndicator.DPad_Right:
					partName = "_[CM]_DPad_Right";
					partName1 = "__CM__DPad_Right";
					partName2 = "__CM__DPad_Right.__CM__DPad_Right";
					indicationKey = "DPad_Right";
					break;
				case ButtonIndication.KeyIndicator.DPad_Up:
					partName = "_[CM]_DPad_Up";
					partName1 = "__CM__DPad_Up";
					partName2 = "__CM__DPad_Up.__CM__DPad_Up";
					indicationKey = "DPad_Up";
					break;
				case ButtonIndication.KeyIndicator.DPad_Down:
					partName = "_[CM]_DPad_Down";
					partName1 = "__CM__DPad_Down";
					partName2 = "__CM__DPad_Down.__CM__DPad_Down";
					indicationKey = "DPad_Down";
					break;
				case ButtonIndication.KeyIndicator.App:
					partName = "_[CM]_AppButton";
					partName1 = "__CM__AppButton";
					partName2 = "__CM__AppButton.__CM__AppButton";
					indicationKey = "AppKey";
					break;
				case ButtonIndication.KeyIndicator.Home:
					partName = "_[CM]_HomeButton";
					partName1 = "__CM__HomeButton";
					partName2 = "__CM__HomeButton.__CM__HomeButton";
					indicationKey = "HomeKey";
					break;
				case ButtonIndication.KeyIndicator.Volume:
					partName = "_[CM]_VolumeKey";
					partName1 = "__CM__VolumeKey";
					partName2 = "__CM__VolumeKey.__CM__VolumeKey";
					indicationKey = "VolumeKey";
					break;
				case ButtonIndication.KeyIndicator.VolumeUp:
					partName = "_[CM]_VolumeUp";
					partName1 = "__CM__VolumeUp";
					partName2 = "__CM__VolumeUp.__CM__VolumeUp";
					indicationKey = "VolumeUp";
					break;
				case ButtonIndication.KeyIndicator.VolumeDown:
					partName = "_[CM]_VolumeDown";
					partName1 = "__CM__VolumeDown";
					partName2 = "__CM__VolumeDown.__CM__VolumeDown";
					indicationKey = "VolumeDown";
					break;
				case ButtonIndication.KeyIndicator.DigitalTrigger:
					partName = "_[CM]_DigitalTriggerKey";
					partName1 = "__CM__DigitalTriggerKey";
					partName2 = "__CM__DigitalTriggerKey.__CM__DigitalTriggerKey";
					indicationKey = "DigitalTriggerKey";
					break;
				case ButtonIndication.KeyIndicator.Bumper:
					partName = "_[CM]_BumperKey";
					partName1 = "__CM__BumperKey";
					partName2 = "__CM__BumperKey.__CM__BumperKey";
					indicationKey = "BumperKey";
					break;
				case ButtonIndication.KeyIndicator.ButtonA:
					partName = "_[CM]_ButtonA";
					partName1 = "__CM__ButtonA";
					partName2 = "__CM__ButtonA.__CM__ButtonA";
					indicationKey = "ButtonA";
					break;
				case ButtonIndication.KeyIndicator.ButtonB:
					partName = "_[CM]_ButtonB";
					partName1 = "__CM__ButtonB";
					partName2 = "__CM__ButtonB.__CM__ButtonB";
					indicationKey = "ButtonB";
					break;
				case ButtonIndication.KeyIndicator.ButtonX:
					partName = "_[CM]_ButtonX";
					partName1 = "__CM__ButtonX";
					partName2 = "__CM__ButtonX.__CM__ButtonX";
					indicationKey = "ButtonX";
					break;
				case ButtonIndication.KeyIndicator.ButtonY:
					partName = "_[CM]_ButtonY";
					partName1 = "__CM__ButtonY";
					partName2 = "__CM__ButtonY.__CM__ButtonY";
					indicationKey = "ButtonY";
					break;
				default:
					partName = "_[CM]_unknown";
					partName1 = "__CM__unknown";
					partName2 = "__CM__unknown.__CM__unknown";
					indicationKey = "unknown";
					PrintDebugLog("Unknown key type!");
					break;
			}

			Transform tmp = transform.Find(partName);
			if (tmp == null)
			{
				tmp = transform.Find(partName1);
				if (tmp == null)
				{
					tmp = transform.Find(partName2);
				}
			}

			if (tmp != null)
			{
				ComponentsIndication tmpCom = new ComponentsIndication();

				tmpCom.Name = partName;
				tmpCom.SourceObject = tmp.gameObject;
				tmpCom.alignment = bi.alignment;
				tmpCom.followButtonRoration = bi.followButtonRotation;

				Vector3 linePos;
				tmpCom.LineIndicator = null;

				linePos = transform.TransformPoint(new Vector3(0, tmp.localPosition.y, tmp.localPosition.z) + bi.indicationOffset);
				Quaternion spawnRot = Quaternion.identity;
				if (bi.followButtonRotation == true)
				{
					spawnRot = transform.rotation;
				}

				GameObject lineGO = Instantiate(linePrefab, linePos, spawnRot);
				lineGO.name = partName + "Line";

				var li = lineGO.GetComponent<IndicatorLine>();
				li.autoLayout = autoLayout;
				li.lineColor = lineColor;
				li.lineLength = lineLength;
				li.startWidth = lineStartWidth;
				li.endWidth = lineEndWidth;
				li.alignment = bi.alignment;
				li.updateMeshSettings();

				if (bi.followButtonRotation == true)
				{
					lineGO.transform.parent = tmpCom.SourceObject.transform;
				}
				lineGO.SetActive(false);
				tmpCom.LineIndicator = lineGO;

				tmpCom.DestObject = null;

				Vector3 spawnPos;
				if (bi.alignment == ButtonIndication.Alignment.RIGHT)
				{
					spawnPos = transform.TransformPoint(new Vector3(lineLength, tmp.localPosition.y, tmp.localPosition.z) + bi.indicationOffset);
				} else
				{
					spawnPos = transform.TransformPoint(new Vector3(lineLength * (-1), tmp.localPosition.y, tmp.localPosition.z) + bi.indicationOffset);
				}

				GameObject destGO = Instantiate(indicatorPrefab, spawnPos, transform.rotation);
				destGO.name = partName + "Ind";
				if (bi.followButtonRotation == true)
				{
					destGO.transform.parent = tmpCom.SourceObject.transform;
				}

				PrintInfoLog(" Source PartName: " + tmp.gameObject.name + " pos: " + tmp.position + " Rot: " + tmp.rotation);
				PrintInfoLog(" Line Name: " + lineGO.name + " pos: " + lineGO.transform.position + " Rot: " + lineGO.transform.rotation);
				PrintInfoLog(" Destination Name: " + destGO.name + " pos: " + destGO.transform.position + " Rot: " + destGO.transform.rotation);

				int childC = destGO.transform.childCount;
				for (int i = 0; i < childC; i++)
				{
					GameObject c = destGO.transform.GetChild(i).gameObject;
					if (bi.alignment == ButtonIndication.Alignment.LEFT)
					{
						float tx = c.transform.localPosition.x;
						c.transform.localPosition = new Vector3(tx * (-1), c.transform.localPosition.y, c.transform.localPosition.z);
					}
					TextMesh tm = c.GetComponent<TextMesh>();
					MeshRenderer mr = c.GetComponent<MeshRenderer>();

					if (tm == null) PrintInfoLog(" tm is null ");
					if (mr == null) PrintInfoLog(" mr is null ");

					if (tm != null && mr != null)
					{
						tm.characterSize = textCharacterSize;
						if (c.name != "Shadow")
						{
							mr.material.SetColor("_Color", textColor);
						} else
						{
							PrintDebugLog(" Shadow found ");
						}
						tm.fontSize = textFontSize;
						if (bi.useMultiLanguage)
						{
							sysLang = rw.getSystemLanguage();
							sysCountry = rw.getSystemCountry();
							PrintDebugLog(" System language is " + sysLang);
							if (sysLang.StartsWith("zh"))
							{
								PrintDebugLog(" Chinese language");
								tm.characterSize = zhCharactarSize;
							}

							// use default string - multi-language
							if (bi.indicationText == "system") {
								tm.text = rw.getString(indicationKey);
								PrintInfoLog(" Name: " + destGO.name + " uses default multi-language -> " + tm.text);
							} else {
								tm.text = rw.getString(bi.indicationText);
								PrintInfoLog(" Name: " + destGO.name + " uses custom multi-language -> " + tm.text);
							}
						} else
						{
							if (bi.indicationText == "system")
								tm.text = indicationKey;
							else
								tm.text = bi.indicationText;

							PrintInfoLog(" Name: " + destGO.name + " didn't uses multi-language -> " + tm.text);
						}

						if (bi.alignment == ButtonIndication.Alignment.LEFT)
						{
							tm.anchor = TextAnchor.MiddleRight;
							tm.alignment = TextAlignment.Right;
						}
					}
				}

				destGO.SetActive(false);
				tmpCom.DestObject = destGO;
				tmpCom.Offset = bi.indicationOffset;

				PrintInfoLog(tmpCom.Name + " line -> " + tmpCom.LineIndicator.name + " destObjName -> " + tmpCom.DestObject.name);
				compInd.Add(tmpCom);
			}
			else
			{
				PrintInfoLog("Neither " + partName + " or " + partName1 + " or " + partName2 + " is not in the model!");
			}
		}

		Emitter = null;
		if (basedOnEmitter)
		{
			WaveVR_RenderModel wrm = this.GetComponentInChildren<WaveVR_RenderModel>();

			if (wrm != null)
			{
				GameObject modelObj = wrm.gameObject;

				int modelchild = modelObj.transform.childCount;
				for (int j = 0; j < modelchild; j++)
				{
					GameObject childName = modelObj.transform.GetChild(j).gameObject;
					if (childName.name == "__CM__Emitter" || childName.name == "_[CM]_Emitter")
					{
						Emitter = childName;
					}
				}
			}
		}

		needRedraw = false;
	}
    private void CollectEffectObjects()     // collect controller object which has effect
    {
        effectMat = Resources.Load("ColorOffsetMaterial") as Material;
        touchMat  = new Material(Shader.Find("Unlit/Texture"));
        if (useSystemConfig)
        {
            PrintInfoLog("use system config in controller model!");
            ReadJsonValues();
        }
        else
        {
            Log.w(LOG_TAG, "use custom config in controller model!");
        }

        var ch = this.transform.childCount;

        PrintDebugLog("childCount: " + ch);
        effectMat.color = buttonEffectColor;

        WaveVR_RenderModel wrm = this.GetComponent <WaveVR_RenderModel>();

        if (wrm != null)
        {
            mergeToOneBone = wrm.mergeToOneBone;
        }

        isTouchPadSetting = GetTouchPadParam();

        for (var j = 0; j < PressEffectNames.Length; j++)
        {
            pressObjectArrays[j]                = new MeshObject();
            pressObjectArrays[j].MeshName       = PressEffectNames[j];
            pressObjectArrays[j].hasEffect      = false;
            pressObjectArrays[j].gameObject     = null;
            pressObjectArrays[j].originPosition = new Vector3(0, 0, 0);
            pressObjectArrays[j].originMat      = null;
            pressObjectArrays[j].effectMat      = null;

            for (int i = 0; i < ch; i++)
            {
                GameObject CM        = this.transform.GetChild(i).gameObject;
                string[]   t         = CM.name.Split("."[0]);
                var        childname = t[0];
                if (pressObjectArrays[j].MeshName == childname)
                {
                    pressObjectArrays[j].gameObject     = CM;
                    pressObjectArrays[j].originPosition = CM.transform.localPosition;
                    pressObjectArrays[j].originMat      = CM.GetComponent <MeshRenderer>().material;
                    pressObjectArrays[j].effectMat      = effectMat;
                    pressObjectArrays[j].hasEffect      = true;

                    if (childname == "__CM__TouchPad")
                    {
                        touchpad     = pressObjectArrays[j].gameObject;
                        touchpadMesh = touchpad.GetComponent <MeshFilter>().mesh;
                        if (touchpadMesh != null)
                        {
                            PrintInfoLog("touchpad is found! ");
                        }
                    }
                    break;
                }
            }

            PrintInfoLog("Press " + pressObjectArrays[j].MeshName + " has effect: " + pressObjectArrays[j].hasEffect);
        }

        for (var j = 0; j < TouchEffectNames.Length; j++)
        {
            touchObjectArrays[j]                = new MeshObject();
            touchObjectArrays[j].MeshName       = TouchEffectNames[j];
            touchObjectArrays[j].hasEffect      = false;
            touchObjectArrays[j].gameObject     = null;
            touchObjectArrays[j].originPosition = new Vector3(0f, 0f, 0f);
            touchObjectArrays[j].originMat      = null;
            touchObjectArrays[j].effectMat      = null;

            for (int i = 0; i < ch; i++)
            {
                GameObject CM        = this.transform.GetChild(i).gameObject;
                string[]   t         = CM.name.Split("."[0]);
                var        childname = t[0];

                if (touchObjectArrays[j].MeshName == childname)
                {
                    touchObjectArrays[j].gameObject     = CM;
                    touchObjectArrays[j].originPosition = CM.transform.localPosition;
                    touchObjectArrays[j].originMat      = CM.GetComponent <MeshRenderer>().material;
                    touchObjectArrays[j].effectMat      = effectMat;
                    touchObjectArrays[j].hasEffect      = true;

                    if (childname == "__CM__TouchPad_Touch")
                    {
                        toucheffectMesh = touchObjectArrays[j].gameObject.GetComponent <MeshFilter>().mesh;
                        if (toucheffectMesh != null)
                        {
                            PrintInfoLog("toucheffectMesh is found! ");
                        }
                    }
                    break;
                }
            }

            PrintInfoLog("Touch " + touchObjectArrays[j].MeshName + " has effect: " + touchObjectArrays[j].hasEffect);
        }

        resetButtonState();
    }
    public void CreateIndicator()
    {
        if (!showIndicator)
        {
            return;
        }
        ClearResourceAndObject();
        Log.d(LOG_TAG, "create Indicator!");
        rw = WaveVR_Resource.instance;
        indicatorPrefab = Resources.Load("ComponentIndicator") as GameObject;

        if (indicatorPrefab == null)
        {
            Log.i(LOG_TAG, "ComponentIndicator is not found!");
            return;
        }
        else
        {
            Log.i(LOG_TAG, "ComponentIndicator is found!");
        }

        linePrefab = Resources.Load("LineIndicator") as GameObject;

        if (linePrefab == null)
        {
            Log.i(LOG_TAG, "LineIndicator is not found!");
            return;
        }
        else
        {
            Log.d(LOG_TAG, "LineIndicator is found!");
        }

        if (hmd == null)
        {
            hmd = WaveVR_Render.Instance.gameObject;
        }

        if (hmd == null)
        {
            Log.i(LOG_TAG, "Can't get HMD!");
            return;
        }

        var gc = transform.childCount;

        for (int i = 0; i < gc; i++)
        {
            GameObject go = transform.GetChild(i).gameObject;

            Log.i(LOG_TAG, "child name is " + go.name);
        }

        Log.i(LOG_TAG, "showIndicatorAngle: " + showIndicatorAngle + ", hideIndicatorByRoll: " + hideIndicatorByRoll + ", basedOnEmitter: " + basedOnEmitter + ", displayPlane: " + displayPlane);
        Log.i(LOG_TAG, "Line settings--\n lineStartWidth: " + lineStartWidth + ", lineEndWidth: " + lineEndWidth + ", lineColor: " + lineColor);
        Log.i(LOG_TAG, "Text settings--\n textCharacterSize: " + textCharacterSize + ", zhCharactarSize: " + zhCharactarSize + ", textFontSize: " + textFontSize + ", textColor: " + textColor);

        body = transform.Find("_[CM]_Body");
        if (body == null)
        {
            body = transform.Find("__CM__Body");
            if (body == null)
            {
                body = transform.Find("__CM__Body.__CM__Body");
                if (body == null)
                {
                    body = transform.Find("Body");
                }
            }
        }

        if (body == null)
        {
            Log.w(LOG_TAG, "Body of the controller can't be found in the model!");
        }

        foreach (AutoButtonIndication bi in buttonIndicationList)
        {
            Log.i(LOG_TAG, "keyType: " + bi.keyType + ", alignment: " + bi.alignment + ", distanceBetweenButtonAndText: " + bi.distanceBetweenButtonAndText + ", distanceBetweenButtonAndLine: " + bi.distanceBetweenButtonAndLine + ", lineLengthAdjustment: " + bi.lineLengthAdjustment + ", useMultiLanguage: " + bi.useMultiLanguage + ", indicationText: " + bi.indicationText);

            // find component by name
            string partName      = null;
            string partName1     = null;
            string partName2     = null;
            string indicationKey = null;
            switch (bi.keyType)
            {
            case AutoButtonIndication.KeyIndicator.Trigger:
                partName      = "_[CM]_TriggerKey";
                partName1     = "__CM__TriggerKey";
                partName2     = "__CM__TriggerKey.__CM__TriggerKey";
                indicationKey = "TriggerKey";
                break;

            case AutoButtonIndication.KeyIndicator.TouchPad:
                partName      = "_[CM]_TouchPad";
                partName1     = "__CM__TouchPad";
                partName2     = "__CM__TouchPad.__CM__TouchPad";
                indicationKey = "TouchPad";
                break;

            case AutoButtonIndication.KeyIndicator.Grip:
                partName      = "_[CM]_Grip";
                partName1     = "__CM__Grip";
                partName2     = "__CM__Grip.__CM__Grip";
                indicationKey = "Grip";
                break;

            case AutoButtonIndication.KeyIndicator.DPad_Left:
                partName      = "_[CM]_DPad_Left";
                partName1     = "__CM__DPad_Left";
                partName2     = "__CM__DPad_Left.__CM__DPad_Left";
                indicationKey = "DPad_Left";
                break;

            case AutoButtonIndication.KeyIndicator.DPad_Right:
                partName      = "_[CM]_DPad_Right";
                partName1     = "__CM__DPad_Right";
                partName2     = "__CM__DPad_Right.__CM__DPad_Right";
                indicationKey = "DPad_Right";
                break;

            case AutoButtonIndication.KeyIndicator.DPad_Up:
                partName      = "_[CM]_DPad_Up";
                partName1     = "__CM__DPad_Up";
                partName2     = "__CM__DPad_Up.__CM__DPad_Up";
                indicationKey = "DPad_Up";
                break;

            case AutoButtonIndication.KeyIndicator.DPad_Down:
                partName      = "_[CM]_DPad_Down";
                partName1     = "__CM__DPad_Down";
                partName2     = "__CM__DPad_Down.__CM__DPad_Down";
                indicationKey = "DPad_Down";
                break;

            case AutoButtonIndication.KeyIndicator.App:
                partName      = "_[CM]_AppButton";
                partName1     = "__CM__AppButton";
                partName2     = "__CM__AppButton.__CM__AppButton";
                indicationKey = "AppKey";
                break;

            case AutoButtonIndication.KeyIndicator.Home:
                partName      = "_[CM]_HomeButton";
                partName1     = "__CM__HomeButton";
                partName2     = "__CM__HomeButton.__CM__HomeButton";
                indicationKey = "HomeKey";
                break;

            case AutoButtonIndication.KeyIndicator.Volume:
                partName      = "_[CM]_VolumeKey";
                partName1     = "__CM__VolumeKey";
                partName2     = "__CM__VolumeKey.__CM__VolumeKey";
                indicationKey = "VolumeKey";
                break;

            case AutoButtonIndication.KeyIndicator.VolumeUp:
                partName      = "_[CM]_VolumeUp";
                partName1     = "__CM__VolumeUp";
                partName2     = "__CM__VolumeUp.__CM__VolumeUp";
                indicationKey = "VolumeUp";
                break;

            case AutoButtonIndication.KeyIndicator.VolumeDown:
                partName      = "_[CM]_VolumeDown";
                partName1     = "__CM__VolumeDown";
                partName2     = "__CM__VolumeDown.__CM__VolumeDown";
                indicationKey = "VolumeDown";
                break;

            case AutoButtonIndication.KeyIndicator.DigitalTrigger:
                partName      = "_[CM]_DigitalTriggerKey";
                partName1     = "__CM__DigitalTriggerKey";
                partName2     = "__CM__DigitalTriggerKey.__CM__DigitalTriggerKey";
                indicationKey = "DigitalTriggerKey";
                break;

            case AutoButtonIndication.KeyIndicator.ButtonA:
                partName      = "_[CM]_ButtonA";
                partName1     = "__CM__ButtonA";
                partName2     = "__CM__ButtonA.__CM__ButtonA";
                indicationKey = "ButtonA";
                break;

            case AutoButtonIndication.KeyIndicator.ButtonB:
                partName      = "_[CM]_ButtonB";
                partName1     = "__CM__ButtonB";
                partName2     = "__CM__ButtonB.__CM__ButtonB";
                indicationKey = "ButtonB";
                break;

            case AutoButtonIndication.KeyIndicator.ButtonX:
                partName      = "_[CM]_ButtonX";
                partName1     = "__CM__ButtonX";
                partName2     = "__CM__ButtonX.__CM__ButtonX";
                indicationKey = "ButtonX";
                break;

            case AutoButtonIndication.KeyIndicator.ButtonY:
                partName      = "_[CM]_ButtonY";
                partName1     = "__CM__ButtonY";
                partName2     = "__CM__ButtonY.__CM__ButtonY";
                indicationKey = "ButtonY";
                break;

            default:
                partName      = "_[CM]_unknown";
                partName1     = "__CM__unknown";
                partName2     = "__CM__unknown.__CM__unknown";
                indicationKey = "unknown";
                Log.d(LOG_TAG, "Unknown key type!");
                break;
            }

            Transform tmp = transform.Find(partName);
            if (tmp == null)
            {
                tmp = transform.Find(partName1);
                if (tmp == null)
                {
                    tmp = transform.Find(partName2);
                }
            }

            if (tmp != null)
            {
                AutoComponentsIndication tmpCom = new AutoComponentsIndication();

                tmpCom.name          = tmp.name;
                tmpCom.sourceObject  = tmp.gameObject;
                tmpCom.indicationKey = indicationKey;
                tmpCom.alignment     = bi.alignment;
                tmpCom.distanceBetweenButtonAndText = bi.distanceBetweenButtonAndText;
                tmpCom.distanceBetweenButtonAndLine = bi.distanceBetweenButtonAndLine;
                tmpCom.lineLengthAdjustment         = bi.lineLengthAdjustment;
                tmpCom.useMultiLanguage             = bi.useMultiLanguage;
                tmpCom.indicationText = bi.indicationText;

                compInd.Add(tmpCom);
            }
            else
            {
                Log.i(LOG_TAG, "Neither " + partName + " or " + partName1 + " or " + partName2 + " is not in the model!");
            }
        }

        Sort();
        FindDisplayPlane();
        DisplayArrangement();
        CreateLineAndText(leftList);
        CreateLineAndText(rightList);

        emitter = null;
        if (basedOnEmitter)
        {
            WaveVR_RenderModel wrm = this.GetComponentInChildren <WaveVR_RenderModel>();

            if (wrm != null)
            {
                GameObject modelObj = wrm.gameObject;

                int modelchild = modelObj.transform.childCount;
                for (int j = 0; j < modelchild; j++)
                {
                    GameObject childName = modelObj.transform.GetChild(j).gameObject;
                    if (childName.name == "__CM__Emitter" || childName.name == "_[CM]_Emitter")
                    {
                        emitter = childName;
                    }
                }
            }
        }

        needRedraw = false;
    }