private void DoPastePointer(Node targetNode) { try { //todo: lots of copy/paste that could be cleaned up and deduped with DoPaste var node = GetClipData(); var sourceObj = node?.Obj as AssetsObject; var targetObj = targetNode?.Obj; var targetOwnerNode = FindFirstParent(targetNode); var targetOwnerObj = targetOwnerNode?.Obj as AssetsObject; var targetDirectParentObj = targetNode?.Parent?.Obj; if (node == null || node.Obj == null || node.StubToNode != null || sourceObj == null || targetObj == null) { return; } if (targetOwnerObj == null) { Log.LogErr($"Tried to paste, but couldn't find the assetsobject owner on node '{targetNode.Text}'"); return; } if (targetDirectParentObj == null) { Log.LogErr($"Tried to paste, but couldn't find the actual parent on node '{targetNode.Text}'"); return; } if (string.IsNullOrWhiteSpace(targetNode.ParentPropertyName)) { Log.LogErr($"Tried to paste, but parent property name was null on node '{targetNode.Text}'"); return; } if (sourceObj.ObjectInfo.ParentFile.Manager != targetOwnerObj.ObjectInfo.ParentFile.Manager) { //can't paste a pointer to a different assets manager instance return; } bool updated = false; var ptrList = targetObj as IEnumerable <ISmartPtr <AssetsObject> >; if (ptrList != null) { try { var pointer = ReflectionHelper.MakeTypedPointer(targetOwnerObj, sourceObj); ReflectionHelper.AddObjectToEnum(pointer, ptrList); updated = true; } catch (Exception ex) { Log.LogErr($"Adding object to collection failed!", ex); return; } } var ptr = targetObj as ISmartPtr <AssetsObject>; if (ptr != null) { try { var pointer = ReflectionHelper.MakeTypedPointer(targetOwnerObj, sourceObj); var oldPointer = ReflectionHelper.GetPtrFromPropName(targetDirectParentObj, targetNode.ParentPropertyName); ReflectionHelper.AssignPtrToPropName(targetDirectParentObj, targetNode.ParentPropertyName, pointer); oldPointer.Dispose(); updated = true; } catch (Exception ex) { Log.LogErr($"Replacing pointer failed on {targetDirectParentObj?.GetType()?.Name}.{targetNode.ParentPropertyName}!"); } } if (updated) { var res = (tvExplorer.Nodes[0].Tag as Node).GetNodePath(targetNode); //update node, hopefully we won't have to repopulate the entire thing? Node newnode = Node.MakeNode(targetOwnerObj); var targetOwnerParentNode = targetOwnerNode.Parent; var idx = targetOwnerNode.Parent.Nodes.IndexOf(targetOwnerNode); targetOwnerParentNode.Nodes.RemoveAt(idx); targetOwnerParentNode.Nodes.Insert(idx, newnode); newnode.Parent = targetOwnerParentNode; newnode.ParentPropertyName = targetOwnerNode.ParentPropertyName; //TODO: find a better way to refresh only the altered tree node and not the whole thing var ds = DataSource; DataSource = null; DataSource = ds; TreeNode tn = tvExplorer.Nodes[0]; while (res.Count > 0) { tn = tn.Nodes[res.Pop()] as TreeNode; } tn.EnsureVisible(); SelectedNode = tn; tn.Expand(); return; } } catch (Exception ex) { Log.LogErr($"Exception trying to paste object!", ex); MessageBox.Show("Failed to paste object!"); } }
// yeesh, so much copy/paste code. I WILL DO BETTER THAN THIS //todo: refactor private void DoPaste(Node targetNode) { try { var node = GetClipData(); var sourceObj = node?.Obj as AssetsObject; var targetObj = targetNode?.Obj; AssetsFile targetFile = null; Node targetOwnerNode = null; AssetsObject targetOwnerObj = null; object targetDirectParentObj = null; if (node == null || node.Obj == null || node.StubToNode != null || sourceObj == null || targetObj == null) { return; } bool isFile = false; if (targetObj is AssetsFile) { isFile = true; targetFile = targetObj as AssetsFile; targetOwnerNode = targetNode.Parent; } else { targetOwnerNode = FindFirstParent(targetNode); targetOwnerObj = targetOwnerNode?.Obj as AssetsObject; targetDirectParentObj = targetNode?.Parent?.Obj; if (targetOwnerObj == null) { Log.LogErr($"Tried to paste, but couldn't find the assetsobject owner on node '{targetNode.Text}'"); return; } if (targetDirectParentObj == null) { Log.LogErr($"Tried to paste, but couldn't find the actual parent on node '{targetNode.Text}'"); return; } if (string.IsNullOrWhiteSpace(targetNode.ParentPropertyName)) { Log.LogErr($"Tried to paste, but parent property name was null on node '{targetNode.Text}'"); return; } targetFile = targetOwnerObj.ObjectInfo.ParentFile; } List <AssetsObject> addedObjects = new List <AssetsObject>(); AssetsObject cloned = null; try { var exclus = GetExclusionsForObject(sourceObj, targetFile); cloned = sourceObj.ObjectInfo.DeepClone(targetFile, addedObjects: addedObjects, exclusions: exclus); } catch (Exception ex) { Log.LogErr($"Exception trying to clone object of type {sourceObj.GetType().Name}!", ex); try { foreach (var ao in addedObjects) { targetFile.DeleteObject(ao); } } catch (Exception ex2) { Log.LogErr("Failed to clean up after bad clone!", ex2); MessageBox.Show("A clone failed and the rollback failed too. The assets files are in an unknown state!"); } return; } bool updated = false; if (isFile) { updated = true; } else { var ptrList = targetObj as IEnumerable <ISmartPtr <AssetsObject> >; if (ptrList != null) { try { var pointer = ReflectionHelper.MakeTypedPointer(targetOwnerObj, cloned); ReflectionHelper.AddObjectToEnum(pointer, ptrList); updated = true; } catch (Exception ex) { Log.LogErr($"Adding object to collection failed!", ex); MessageBox.Show("Object was created, but could not be attached to the collection!"); return; } } var ptr = targetObj as ISmartPtr <AssetsObject>; if (ptr != null) { try { var pointer = ReflectionHelper.MakeTypedPointer(targetOwnerObj, cloned); var oldPointer = ReflectionHelper.GetPtrFromPropName(targetDirectParentObj, targetNode.ParentPropertyName); ReflectionHelper.AssignPtrToPropName(targetDirectParentObj, targetNode.ParentPropertyName, pointer); oldPointer.Dispose(); updated = true; } catch (Exception ex) { Log.LogErr($"Replacing pointer failed on {targetDirectParentObj?.GetType()?.Name}.{targetNode.ParentPropertyName}!"); } } } if (updated) { var res = (tvExplorer.Nodes[0].Tag as Node).GetNodePath(targetNode); //update node, hopefully we won't have to repopulate the entire thing? if (!isFile) { Node newNode = Node.MakeNode(targetOwnerObj); var targetOwnerParentNode = targetOwnerNode.Parent; var idx = targetOwnerNode.Parent.Nodes.IndexOf(targetOwnerNode); targetOwnerParentNode.Nodes.RemoveAt(idx); targetOwnerParentNode.Nodes.Insert(idx, newNode); newNode.Parent = targetOwnerParentNode; newNode.ParentPropertyName = targetOwnerNode.ParentPropertyName; } else { Node newNode = Node.MakeNode((AssetsFile)targetObj); var idx = targetNode.Parent.Nodes.IndexOf(targetNode); targetNode.Parent.Nodes.RemoveAt(idx); targetNode.Parent.Nodes.Insert(idx, newNode); newNode.Parent = targetNode; newNode.ParentPropertyName = null; } //TODO: find a better way to refresh only the altered tree node and not the whole thing var ds = DataSource; DataSource = null; DataSource = ds; TreeNode tn = tvExplorer.Nodes[0]; while (res.Count > 0) { tn = tn.Nodes[res.Pop()] as TreeNode; } tn.EnsureVisible(); SelectedNode = tn; tn.Expand(); return; } } catch (Exception ex) { Log.LogErr($"Exception trying to paste object!", ex); MessageBox.Show("Failed to paste object!"); } }