public Action GetUpdateTransformAction(Transform newt) { if (WrappedObject is PARAM.Row || WrappedObject is MergedParamRow) { var actions = new List <Action>(); float roty = newt.EulerRotation.Y * Utils.Rad2Deg - 180.0f; actions.Add(GetPropertyChangeAction("PositionX", newt.Position.X)); actions.Add(GetPropertyChangeAction("PositionY", newt.Position.Y)); actions.Add(GetPropertyChangeAction("PositionZ", newt.Position.Z)); actions.Add(GetPropertyChangeAction("RotationX", newt.EulerRotation.X * Utils.Rad2Deg)); actions.Add(GetPropertyChangeAction("RotationY", roty)); actions.Add(GetPropertyChangeAction("RotationZ", newt.EulerRotation.Z * Utils.Rad2Deg)); var act = new CompoundAction(actions); act.SetPostExecutionAction((undo) => { UpdateRenderModel(); }); return(act); } else { var act = new PropertiesChangedAction(WrappedObject); var prop = WrappedObject.GetType().GetProperty("Position"); act.AddPropertyChange(prop, newt.Position); prop = WrappedObject.GetType().GetProperty("Rotation"); if (prop != null) { if (IsRotationPropertyRadians("Rotation")) { if (IsRotationXZY("Rotation")) { act.AddPropertyChange(prop, newt.EulerRotationXZY); } else { act.AddPropertyChange(prop, newt.EulerRotation); } } else { if (IsRotationXZY("Rotation")) { act.AddPropertyChange(prop, newt.EulerRotationXZY * Utils.Rad2Deg); } else { act.AddPropertyChange(prop, newt.EulerRotation * Utils.Rad2Deg); } } } act.SetPostExecutionAction((undo) => { UpdateRenderModel(); }); return(act); } }
private void ChangeProperty(object prop, Entity selection, object obj, object newval, ref bool committed, bool shouldUpdateVisual, bool destroyRenderModel, int arrayindex = -1) { if (prop == _changingPropery && _lastUncommittedAction != null && ContextActionManager.PeekUndoAction() == _lastUncommittedAction) { ContextActionManager.UndoAction(); } else { _lastUncommittedAction = null; } if (_changingObject != null && selection != null && selection.WrappedObject != _changingObject) { committed = true; } else { PropertiesChangedAction action; if (arrayindex != -1) { action = new PropertiesChangedAction((PropertyInfo)prop, arrayindex, obj, newval); } else { action = new PropertiesChangedAction((PropertyInfo)prop, obj, newval); } if (shouldUpdateVisual && selection != null) { action.SetPostExecutionAction((undo) => { if (destroyRenderModel) { if (selection.RenderSceneMesh != null) { selection.RenderSceneMesh.Dispose(); selection.RenderSceneMesh = null; } } selection.UpdateRenderModel(); }); } ContextActionManager.ExecuteAction(action); _lastUncommittedAction = action; _changingPropery = prop; // ChangingObject = selection.MsbObject; _changingObject = selection != null ? selection.WrappedObject : obj; } }
private void ChangeProperty(object prop, object obj, object newval, ref bool committed, int arrayindex = -1) { if (committed) { PropertiesChangedAction action; if (arrayindex != -1) { action = new PropertiesChangedAction((PropertyInfo)prop, arrayindex, obj, newval); } else { action = new PropertiesChangedAction((PropertyInfo)prop, obj, newval); } ContextActionManager.ExecuteAction(action); } }
private void PropEditorGeneric(Entity selection, object target = null, bool decorate = true) { var obj = (target == null) ? selection.WrappedObject : target; var type = obj.GetType(); if (!_propCache.ContainsKey(type.FullName)) { _propCache.Add(type.FullName, type.GetProperties(BindingFlags.Instance | BindingFlags.Public)); } var properties = _propCache[type.FullName]; if (decorate) { ImGui.Columns(2); ImGui.Separator(); ImGui.Text("Object Type"); ImGui.NextColumn(); ImGui.Text(type.Name); ImGui.NextColumn(); } // Custom editors if (type == typeof(FLVER2.BufferLayout)) { PropEditorFlverLayout(selection, (FLVER2.BufferLayout)obj); } else { int id = 0; foreach (var prop in properties) { if (!prop.CanWrite && !prop.PropertyType.IsArray) { continue; } if (prop.GetCustomAttribute <HideProperty>() != null) { continue; } ImGui.PushID(id); ImGui.AlignTextToFramePadding(); // ImGui.AlignTextToFramePadding(); var typ = prop.PropertyType; if (typ.IsArray) { Array a = (Array)prop.GetValue(obj); for (int i = 0; i < a.Length; i++) { ImGui.PushID(i); var arrtyp = typ.GetElementType(); if (arrtyp.IsClass && arrtyp != typeof(string) && !arrtyp.IsArray) { bool open = ImGui.TreeNodeEx($@"{prop.Name}[{i}]", ImGuiTreeNodeFlags.DefaultOpen); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var o = a.GetValue(i); ImGui.Text(o.GetType().Name); ImGui.NextColumn(); if (open) { PropEditorGeneric(selection, o, false); ImGui.TreePop(); } ImGui.PopID(); } else { ImGui.Text($@"{prop.Name}[{i}]"); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var oldval = a.GetValue(i); bool shouldUpdateVisual = false; bool changed = false; object newval = null; changed = PropertyRow(typ.GetElementType(), oldval, out newval); // PropertyContextMenu(prop); if (ImGui.IsItemActive() && !ImGui.IsWindowFocused()) { ImGui.SetItemDefaultFocus(); } bool committed = ImGui.IsItemDeactivatedAfterEdit(); UpdateProperty(prop, selection, obj, newval, changed, committed, shouldUpdateVisual, false, i); ImGui.NextColumn(); ImGui.PopID(); } } ImGui.PopID(); } else if (typ.IsGenericType && typ.GetGenericTypeDefinition() == typeof(List <>)) { object l = prop.GetValue(obj); PropertyInfo itemprop = l.GetType().GetProperty("Item"); int count = (int)l.GetType().GetProperty("Count").GetValue(l); for (int i = 0; i < count; i++) { ImGui.PushID(i); var arrtyp = typ.GetGenericArguments()[0]; if (arrtyp.IsClass && arrtyp != typeof(string) && !arrtyp.IsArray) { bool open = ImGui.TreeNodeEx($@"{prop.Name}[{i}]", ImGuiTreeNodeFlags.DefaultOpen); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var o = itemprop.GetValue(l, new object[] { i }); ImGui.Text(o.GetType().Name); ImGui.NextColumn(); if (open) { PropEditorGeneric(selection, o, false); ImGui.TreePop(); } ImGui.PopID(); } else { ImGui.Text($@"{prop.Name}[{i}]"); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var oldval = itemprop.GetValue(l, new object[] { i }); bool shouldUpdateVisual = false; bool changed = false; object newval = null; changed = PropertyRow(arrtyp, oldval, out newval); PropertyContextMenu(obj, prop); if (ImGui.IsItemActive() && !ImGui.IsWindowFocused()) { ImGui.SetItemDefaultFocus(); } bool committed = ImGui.IsItemDeactivatedAfterEdit(); UpdateProperty(prop, selection, obj, newval, changed, committed, shouldUpdateVisual, false, i); ImGui.NextColumn(); ImGui.PopID(); } } ImGui.PopID(); } // TODO: find a better place to handle this special case (maybe) else if (typ.IsClass && typ == typeof(MSB.Shape)) { bool open = ImGui.TreeNodeEx(prop.Name, ImGuiTreeNodeFlags.DefaultOpen); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var o = prop.GetValue(obj); var shapetype = Enum.Parse <RegionShape>(o.GetType().Name); int shap = (int)shapetype; if (ImGui.Combo("##shapecombo", ref shap, _regionShapes, _regionShapes.Length)) { MSB.Shape newshape; switch ((RegionShape)shap) { case RegionShape.Box: newshape = new MSB.Shape.Box(); break; case RegionShape.Point: newshape = new MSB.Shape.Point(); break; case RegionShape.Cylinder: newshape = new MSB.Shape.Cylinder(); break; case RegionShape.Sphere: newshape = new MSB.Shape.Sphere(); break; case RegionShape.Composite: newshape = new MSB.Shape.Composite(); break; default: throw new Exception("Invalid shape"); } //UpdateProperty(prop, selection, obj, newshape, true, true, true, true); var action = new PropertiesChangedAction((PropertyInfo)prop, obj, newshape); action.SetPostExecutionAction((undo) => { bool selected = false; if (selection.RenderSceneMesh != null) { selected = selection.RenderSceneMesh.RenderSelectionOutline; selection.RenderSceneMesh.Dispose(); selection.RenderSceneMesh = null; } selection.UpdateRenderModel(); selection.RenderSceneMesh.RenderSelectionOutline = selected; }); ContextActionManager.ExecuteAction(action); } ImGui.NextColumn(); if (open) { PropEditorGeneric(selection, o, false); ImGui.TreePop(); } ImGui.PopID(); } else if (typ.IsClass && typ != typeof(string) && !typ.IsArray) { bool open = ImGui.TreeNodeEx(prop.Name, ImGuiTreeNodeFlags.DefaultOpen); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var o = prop.GetValue(obj); ImGui.Text(o.GetType().Name); ImGui.NextColumn(); if (open) { PropEditorGeneric(selection, o, false); ImGui.TreePop(); } ImGui.PopID(); } else { ImGui.Text(prop.Name); ImGui.NextColumn(); ImGui.SetNextItemWidth(-1); var oldval = prop.GetValue(obj); bool shouldUpdateVisual = false; bool changed = false; object newval = null; changed = PropertyRow(typ, oldval, out newval, selection, prop.Name); PropertyContextMenu(obj, prop); if (ImGui.IsItemActive() && !ImGui.IsWindowFocused()) { ImGui.SetItemDefaultFocus(); } bool committed = ImGui.IsItemDeactivatedAfterEdit(); UpdateProperty(prop, selection, obj, newval, changed, committed, shouldUpdateVisual, false); ImGui.NextColumn(); ImGui.PopID(); } id++; } } if (decorate) { ImGui.Columns(1); if (selection.References != null) { ImGui.NewLine(); ImGui.Text("References: "); foreach (var m in selection.References) { foreach (var n in m.Value) { ImGui.Text(n.PrettyName); } } } ImGui.NewLine(); ImGui.Text("Objects referencing this object:"); foreach (var m in selection.GetReferencingObjects()) { ImGui.Text(m.PrettyName); } } }
private void ChangeProperty(object prop, Entity selection, object obj, object newval, bool changed, bool committed, bool shouldUpdateVisual, int arrayindex = -1) { if (changed) { if (prop == ChangingPropery && LastUncommittedAction != null) { if (ContextActionManager.PeekUndoAction() == LastUncommittedAction) { ContextActionManager.UndoAction(); } else { LastUncommittedAction = null; } } else { LastUncommittedAction = null; } if (ChangingObject != null && selection != null && selection.WrappedObject != ChangingObject) { committed = true; } else { PropertiesChangedAction action; if (arrayindex != -1) { action = new PropertiesChangedAction((PropertyInfo)prop, arrayindex, obj, newval); } else { action = new PropertiesChangedAction((PropertyInfo)prop, obj, newval); } if (shouldUpdateVisual && selection != null) { action.SetPostExecutionAction((undo) => { selection.UpdateRenderModel(); }); } ContextActionManager.ExecuteAction(action); LastUncommittedAction = action; ChangingPropery = prop; //ChangingObject = selection.MsbObject; ChangingObject = selection != null ? selection.WrappedObject : obj; } } if (committed) { // Invalidate name cache if (selection != null) { selection.Name = null; } // Undo and redo the last action with a rendering update if (LastUncommittedAction != null && ContextActionManager.PeekUndoAction() == LastUncommittedAction) { if (LastUncommittedAction is PropertiesChangedAction a) { // Kinda a hack to prevent a jumping glitch a.SetPostExecutionAction(null); ContextActionManager.UndoAction(); if (selection != null) { a.SetPostExecutionAction((undo) => { selection.UpdateRenderModel(); }); } ContextActionManager.ExecuteAction(a); } } LastUncommittedAction = null; ChangingPropery = null; ChangingObject = null; } }