void OnGUI() { GUILayout.Space(10); GUILayout.Label("Select the lesson when opening Unity:", headerStyle); var newlesson = (LessonChoice)EditorGUILayout.EnumPopup("Lesson", Context.Lesson); //update DB if new lesson if ((int)newlesson > 0 && Context.Lesson != newlesson) { Context.Lesson = newlesson; DataLogging.UpdateChallengeInDatabase(ChallengeEventTypes.Lesson, newlesson.ToString()); } if ((int)Context.Lesson < 1) { GUILayout.Label("Please select a lesson", errorStyle); } GUILayout.Space(20); GUILayout.Label("Select the challenge and click the appropriate button at the beginning and end:", headerStyle); UME.Context.Challenge = (ChallengeChoice)EditorGUILayout.EnumPopup("Challenge", Context.Challenge); // during challenge, add a button to stop the challenge and add buttons to start/stop group help if (Context.inChallenge) { GUILayout.Label("Challenge Status: Started!", okStyle); //button to end challenge if (GUILayout.Button("End of challenge")) { Context.inChallenge = false; Context.EndChallengeTime = DataLogging.CurrentTimeStamp(); DataLogging.UpdateChallengeInDatabase(ChallengeEventTypes.Challenge); if (Context.inGroupHelp) { Context.inGroupHelp = false; Context.EndGroupHelpTime = Context.EndChallengeTime; GenericMenu mm = new GenericMenu(); foreach (KeyValuePair <string, string> item in Context.SkillSet) { mm.AddItem(new GUIContent(item.Value), false, GroupHelpPopUp, item.Key); } mm.ShowAsContext(); } } //Group help during challenges GUILayout.Space(10); GUILayout.Label("Group help mode during challenge", headerStyle); if (Context.inGroupHelp) { GUILayout.Label("In Help Mode!", okStyle); if (GUILayout.Button("End group help")) { Context.inGroupHelp = false; Context.EndGroupHelpTime = DataLogging.CurrentTimeStamp(); //pop up to select target skill GenericMenu mm = new GenericMenu(); foreach (KeyValuePair <string, string> item in Context.SkillSet) { mm.AddItem(new GUIContent(item.Value), false, GroupHelpPopUp, item.Key); } mm.ShowAsContext(); } } else { if (GUILayout.Button("Start group help")) { Context.inGroupHelp = true; Context.StartGroupHelpTime = DataLogging.CurrentTimeStamp(); } } } //not in challenge, just add a button to start a challenge else { GUILayout.Label("Challenge Status: Stopped / Not started ", errorStyle); if (GUILayout.Button("Start challenge")) { if ((int)Context.Lesson > 0 && (int)Context.Challenge > 0) { Context.inChallenge = true; Context.StartChallengeTime = DataLogging.CurrentTimeStamp(); //ComSocket.Broadcast("{\"target\":\"unity\",\"cmd\":\"start_challenge\",\"params\":[]}"); } } } }
//Skill set pop up after help mode (register selected skill in DB) static void GroupHelpPopUp(object obj) { DataLogging.UpdateChallengeInDatabase(ChallengeEventTypes.GroupHelp, obj.ToString()); }
//update challenge public static void UpdateChallengeInDatabase(UME.ChallengeEventTypes ev, string Params = "") { var conn = new SqliteConnection("URI=file:" + TelemetryDbPath); conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = "INSERT INTO " + ChallengeTableColumns + " VALUES (@user_id, @session_id, @lesson_id, @event, @challenge_id, @login, @start_time, @end_time, @params)"; var evname = ""; var starttime = ""; var endtime = ""; switch (ev) { case ChallengeEventTypes.Challenge: evname = "Challenge"; starttime = Context.StartChallengeTime; endtime = Context.EndChallengeTime; break; case ChallengeEventTypes.GroupHelp: evname = "GroupHelp"; starttime = Context.StartGroupHelpTime; endtime = Context.EndGroupHelpTime; break; case ChallengeEventTypes.Lesson: evname = "Lesson"; starttime = DataLogging.CurrentTimeStamp(); break; } cmd.Parameters.Add(new SqliteParameter { ParameterName = "user_id", Value = Context.User }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "session_id", Value = Context.Session }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "lesson_id", Value = Context.Lesson }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "event", Value = evname }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "challenge_id", Value = (int)Context.Challenge }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "login", Value = Context.Login }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "start_time", Value = starttime }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "end_time", Value = endtime }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "params", Value = Params }); cmd.ExecuteNonQuery(); cmd.Dispose(); cmd = null; conn.Close(); }
//Write in DB //static void UpdateDatabase(string Mode, string TargetName, string actionModality, string ActionType, string actionparams) public static void UpdateDatabase(string ActionType, string Modality, string Time = "", string Mode = "", string Tool = "", string Area = "", string Target = "", string Params = "") { var conn = new SqliteConnection("URI=file:" + TelemetryDbPath); conn.Open(); var cmd = conn.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = "INSERT INTO " + ActionTableColumns + " VALUES (@user_id, @session_id, @lesson_id, @challenge_id, @login, @time, @editormode, @curtool, @actionType , @keyOrMouse, @area, @target, @params)"; if (Area == "") { Area = (UnityEditor.EditorWindow.mouseOverWindow ? UnityEditor.EditorWindow.mouseOverWindow.titleContent.text : ""); } if (Mode == "") { Mode = (EditorApplication.isPlaying ? "Play" : "Edit"); } if (Tool == "") { Tool = TransformToolSelected(); } cmd.Parameters.Add(new SqliteParameter { ParameterName = "user_id", Value = Context.User }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "session_id", Value = Context.Session }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "lesson_id", Value = Context.Lesson }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "challenge_id", Value = (Context.inChallenge ? (int)Context.Challenge : -1) }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "login", Value = Context.Login }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "time", Value = (Time == "" ? DataLogging.CurrentTimeStamp() : Time) }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "editormode", Value = Mode }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "curtool", Value = Tool }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "actionType", Value = ActionType }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "keyOrMouse", Value = Modality }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "area", Value = Area }); //logs interface area of scene, project and hierarchy ONLY when an object in any of them is selected. Doesn't detect mouseclicks in Inspector window. cmd.Parameters.Add(new SqliteParameter { ParameterName = "target", Value = Target }); cmd.Parameters.Add(new SqliteParameter { ParameterName = "params", Value = Params }); cmd.ExecuteNonQuery(); cmd.Dispose(); cmd = null; /*if( (System.DateTime.Now.Ticks - DataLogging.lastDBwrite > 3000000000) ){ * DataLogging.WriteDb(); * }*/ DataLogging.lastDBwrite = System.DateTime.Now.Ticks; conn.Close(); }
//track events in the scene and teacher help mode static void OnSceneGUI(SceneView sceneview) { //the following line allows all mouseUp, mouseDown and mouseDrag events to be detected, but blocks object to be selected successfully //HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive)); drawHelpFrame(); var e = Event.current; if (e.isMouse) { //Mouse Vector2 initPos = e.mousePosition; //right click drag if (e.type == EventType.MouseDrag && e.button == 1) { if ((System.DateTime.Now.Ticks - DataLogging.lastpan) > 5000000) { if (debug) { UnityEngine.Debug.Log("Right Drag performed"); } UpdateDatabase(ActionType: "Free-Pan", Modality: "Mouse", Params: e.delta.ToString()); DataLogging.lastpan = System.DateTime.Now.Ticks; } } if (debug) { if (e.type == EventType.MouseUp) { //Left Mouse Button if (e.button == 0) { UnityEngine.Debug.Log("Left mouse click at coordinates: " + initPos.ToString()); } //Right Mouse Button else if (e.button == 1) { UnityEngine.Debug.Log("Right Click"); } } } } else if (e.isScrollWheel) { //Mouse Scroll wheel if ((System.DateTime.Now.Ticks - DataLogging.lastscroll) > 5000000) { if (debug) { UnityEngine.Debug.Log("Mouse scroll wheel used " + e.delta); } UpdateDatabase(ActionType: "Zoom", Modality: "Mouse", Target: DataLogging.getCurrentSelectedObjectNames(), Params: e.delta.y < 0 ? "Zoom-in" : "Zoom-out"); DataLogging.lastscroll = System.DateTime.Now.Ticks; } } else { //Keyboard if (e != null && e.keyCode != KeyCode.None) { //Control based special commands //Undo if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Z) { if (debug) { UnityEngine.Debug.Log("Ctrl Z performed"); } UpdateDatabase(ActionType: "Cancel", Modality: "HotKey"); } //Redo else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Y) { if (debug) { UnityEngine.Debug.Log("Ctrl Y performed"); } UpdateDatabase(ActionType: "Redo", Modality: "HotKey"); } //Select all else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.A) { if (debug) { UnityEngine.Debug.Log("Ctrl A performed"); } UpdateDatabase(ActionType: "SelectAll", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames()); } //Save else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.S) { if (debug) { UnityEngine.Debug.Log("Ctrl S perfomed"); } UpdateDatabase(ActionType: "Save as", Modality: "HotKey"); } //Duplicate else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.D) { if (debug) { UnityEngine.Debug.Log("Ctrl D perfomed"); } UpdateDatabase(ActionType: "Duplicate", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames()); } //Copy else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.C) { if (debug) { UnityEngine.Debug.Log("Ctrl C perfomed"); } UpdateDatabase(ActionType: "Copy", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames()); } //Paste else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.V) { if (debug) { UnityEngine.Debug.Log("Ctrl V perfomed"); } UpdateDatabase(ActionType: "Paste", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames()); } //Teacher help else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Alpha1) { if (isTeacherHelping) //exit teacher help mode { UnityEngine.Debug.Log(""); isTeacherHelping = false; UpdateDatabase(ActionType: "TeacherHelp", Modality: "HotKey", Params: "EndHelp " + DataLogging.opened_audio_file); //sceneview.RemoveNotification(); DataLogging.opened_audio_file = ""; if (DataLogging.procaudio != null && !DataLogging.procaudio.HasExited) { DataLogging.procaudio.Kill(); } //display help menu GenericMenu mm = new GenericMenu(); var m_scenename = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; foreach (KeyValuePair <string, string> item in Context.SkillSet) { if (m_scenename == "challenge 1" && item.Value.Contains("Lesson1")) { mm.AddItem(new GUIContent(item.Value.Replace("Lesson1/", "")), false, TeacherHelpPopUp, item.Key); } else if (m_scenename == "challenge 2" && item.Value.Contains("Lesson2")) { mm.AddItem(new GUIContent(item.Value.Replace("Lesson2/", "")), false, TeacherHelpPopUp, item.Key); } else if (m_scenename == "challenge 3" && item.Value.Contains("Lesson3")) { mm.AddItem(new GUIContent(item.Value.Replace("Lesson3/", "")), false, TeacherHelpPopUp, item.Key); } } mm.AddSeparator(""); mm.AddSeparator(""); mm.AddSeparator(""); mm.AddSeparator(""); mm.AddSeparator(""); foreach (KeyValuePair <string, string> item in Context.SkillSet) { mm.AddItem(new GUIContent(item.Value), false, TeacherHelpPopUp, item.Key); } mm.ShowAsContext(); } else //enter teacher help mode { UnityEngine.Debug.Log("Teacher help mode"); isTeacherHelping = true; UpdateDatabase(ActionType: "TeacherHelp", Modality: "Keyboard", Params: "StartHelp"); //sceneview.ShowNotification(new GUIContent("Help")); DataLogging.procaudio = new Process(); DataLogging.procaudio.StartInfo.FileName = "arecord"; DataLogging.procaudio.StartInfo.WorkingDirectory = DataLogging.RecordingDbPath + "/"; DataLogging.opened_audio_file = "-d 180 -f cd helpaudiorecord_" + Context.User + "_" + Context.Session + "_" + System.DateTime.Now.Ticks; DataLogging.procaudio.StartInfo.Arguments = DataLogging.opened_audio_file; DataLogging.procaudio.Start(); } } //Everything except control based special commands else if (e != null && e.keyCode != KeyCode.None && e.keyCode != KeyCode.LeftControl && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Z) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Y) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.A) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.S) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.C) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.V) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.D) && !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Alpha1)) { //Pan with arrows, maybe make it KeyUp (or maybe even let it be done by the next elseif block for KeyUp events if (e.type == EventType.KeyDown) { if (e.keyCode == KeyCode.Delete) { UpdateDatabase(ActionType: "Delete", Modality: "HotKey", Target: DataLogging.last_selected_object); } else if (e.keyCode == KeyCode.F) { if (debug) { UnityEngine.Debug.Log("Focus performed with F"); } UpdateDatabase(ActionType: "Focus", Modality: "HotKey", Target: getCurrentSelectedObjectNames()); } /*else{ * if(debug) UnityEngine.Debug.Log("Key pressed in editor: " + e.keyCode); * UpdateDatabase(ActionType: "keyPressed", Modality: "Keyboard", Target: getCurrentSelectedObjectNames(), Params: e.keyCode.ToString()); * } */ } //Any Key tracking on KeyUp. else if (e.type == EventType.KeyUp) { //if(debug) UnityEngine.Debug.Log("Key Up in editor: " + e.keyCode); if (e.keyCode == KeyCode.UpArrow) { UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Up"); } else if (e.keyCode == KeyCode.DownArrow) { UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Down"); } else if (e.keyCode == KeyCode.LeftArrow) { UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Left"); } else if (e.keyCode == KeyCode.RightArrow) { UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Right"); } else { if (debug) { UnityEngine.Debug.Log("Key up in editor: " + e.keyCode); } UpdateDatabase(ActionType: "KeyPressed", Modality: "Keyboard", Target: getCurrentSelectedObjectNames(), Params: e.keyCode.ToString()); } } } } } }
//Returns initial and final values of the current property being modified static UnityEditor.UndoPropertyModification[] OnPropertyModification(UnityEditor.UndoPropertyModification[] modifications) { var m_params = ""; //if new group of property change, write previous group in DB if (DataLogging.current_action_group != Undo.GetCurrentGroup()) { if (DataLogging.current_action_group != -1) { if (DataLogging.new_property_group != "" && DataLogging.property_group != "") { m_params = (DataLogging.current_action_group + "--" + DataLogging.new_property_group + "--" + DataLogging.last_action_value_in_group + "--" + DataLogging.property_group + "--" + DataLogging.first_action_value_in_group); UpdateDatabase(ActionType: "ChangeProperty", Modality: (DataLogging.area_group == "Scene" ? "Mouse" : "Keyboard"), Time: DataLogging.start_time_group, Tool: DataLogging.tool_group, Area: DataLogging.area_group, Target: DataLogging.target_group, Params: m_params); } } DataLogging.first_action_value_in_group = ""; DataLogging.last_action_value_in_group = ""; DataLogging.property_group = ""; DataLogging.new_property_group = ""; DataLogging.current_action_group = Undo.GetCurrentGroup(); DataLogging.target_group = ""; DataLogging.start_time_group = ""; DataLogging.tool_group = ""; //var transform_values = ""; foreach (UnityEditor.UndoPropertyModification m in modifications) { if (m.currentValue.target.ToString().Contains("UnityEngine.Transform")) { if (debug) { UnityEngine.Debug.Log(Undo.GetCurrentGroup() + "UNDO transform" + m.currentValue.target + " " + m.currentValue.propertyPath); } /*if (transform_values == ""){ * if(UnityEditor.Selection.objects != null){ * foreach(GameObject ob in UnityEditor.Selection.objects){ * var comp = ob.GetComponent(typeof(UnityEngine.Transform)); * transform_values += ob.name+"[P"+comp.transform.localPosition+",R"+comp.transform.localRotation+",S"+comp.transform.localScale+"]"; * } * } * } */ } else { if (debug) { UnityEngine.Debug.Log("UNDO notransform" + m.currentValue.target + " " + m.currentValue.propertyPath + " " + Undo.GetCurrentGroupName() + " " + Undo.GetCurrentGroup()); } //UpdateDatabase(ActionType: "ChangeProperty", Modality: "Inspector", Target: getCurrentSelectedObjectNames(), Params: m_params); } if (DataLogging.start_time_group == "") { DataLogging.start_time_group = DataLogging.CurrentTimeStamp(); } if (DataLogging.target_group == "") { DataLogging.target_group = DataLogging.getCurrentSelectedObjectNames(); } if (DataLogging.tool_group == "") { DataLogging.tool_group = DataLogging.TransformToolSelected(); } DataLogging.first_action_value_in_group += "[" + (m.previousValue.objectReference ? m.previousValue.objectReference.ToString() : m.previousValue.value.ToString()) + "]"; DataLogging.last_action_value_in_group += "[" + (m.currentValue.objectReference ? m.currentValue.objectReference.ToString() : m.currentValue.value.ToString()) + "]"; DataLogging.property_group += "[" + m.currentValue.target + "--" + m.currentValue.propertyPath + "]"; DataLogging.area_group = (UnityEditor.EditorWindow.mouseOverWindow != null ? UnityEditor.EditorWindow.mouseOverWindow.titleContent.text : ""); DataLogging.new_property_group = property_group; } } //during property change (relevant for transform drag and drop, or writing) else { DataLogging.last_action_value_in_group = ""; DataLogging.new_property_group = ""; foreach (UnityEditor.UndoPropertyModification m in modifications) { DataLogging.last_action_value_in_group += "[" + (m.currentValue.objectReference ? m.currentValue.objectReference.ToString() : m.currentValue.value.ToString()) + "]"; DataLogging.new_property_group += "[" + m.currentValue.target + "--" + m.currentValue.propertyPath + "]"; DataLogging.area_group = (UnityEditor.EditorWindow.mouseOverWindow != null ? UnityEditor.EditorWindow.mouseOverWindow.titleContent.text : ""); } } return(modifications); }