// ----------------------------------------------------------------------- void DisplayObjectErrorsAndWarnings(List <ErrorWarning> errors, List <ErrorWarning> warnings) { // -- Determine wich objects have errors or warnings -- var objectIds = P.append(P.map(e => e.ObjectId, errors), P.map(w => w.ObjectId, warnings)); objectIds = P.removeDuplicates(objectIds); // -- Display the errors/warnings on the objects in the graph -- foreach (var id in objectIds) { // -- Determine if node is visible -- var node = IStorage[id]; if (!DisplayRoot.IsParentOf(node)) { continue; } var pos = node.GlobalPosition; if (!VisibleGraphRect.Contains(pos)) { continue; } // -- Determine errors/warnings for this particular node -- var nodeErrors = P.filter(e => e.ObjectId == id, errors); var nodeWarnings = P.filter(w => w.ObjectId == id, warnings); // -- Display the appropriate error/warning icon -- var r = Math3D.BuildRectCenteredAt(pos, 32f, 32f); r = myGraphics.TranslateAndScale(r); DisplayErrorsAndWarningAt(r, nodeErrors, nodeWarnings); } }
// ---------------------------------------------------------------------- public static iCS_EditorObject WrapMultiSelectionInPackage(iCS_IStorage iStorage) { if (iStorage == null) { return(null); } if (!IsCreationAllowed()) { return(null); } var selectedObjects = iStorage.FilterMultiSelectionForWrapInPackage(); if (selectedObjects == null || selectedObjects.Length == 0) { return(null); } iCS_EditorObject package = null; OpenTransaction(iStorage); try { iStorage.AnimateGraph(null, _ => { var childrenRects = P.map(n => n.GlobalRect, selectedObjects); package = iStorage.WrapInPackage(selectedObjects); if (package != null) { var r = Math3D.Union(childrenRects); var pos = Math3D.Middle(r); package.SetInitialPosition(Math3D.Middle(r)); iStorage.ForcedRelayoutOfTree(); package.myAnimatedRect.StartValue = BuildRect(pos, Vector2.zero); for (int i = 0; i < selectedObjects.Length; ++i) { selectedObjects[i].SetInitialPosition(iCS_EditorObject.PositionFrom(childrenRects[i])); selectedObjects[i].LocalSize = iCS_EditorObject.SizeFrom(childrenRects[i]); } iStorage.ForcedRelayoutOfTree(); iStorage.ReduceCollisionOffset(); } else { Debug.LogWarning("iCanScript: Unable to create a suitable package."); } } ); } catch (System.Exception) { CancelTransaction(iStorage); return(null); } if (package == null) { CancelTransaction(iStorage); return(null); } CloseTransaction(iStorage, "Wrap Selection"); SystemEvents.AnnounceVisualScriptElementAdded(package); return(package); }
// ---------------------------------------------------------------------- public static void DeleteKeepChildren(iCS_EditorObject obj) { if (!IsDeletionAllowed()) { return; } var iStorage = obj.IStorage; OpenTransaction(iStorage); try { var newParent = obj.ParentNode; var childNodes = obj.BuildListOfChildNodes(_ => true); var childPos = P.map(n => n.GlobalPosition, childNodes); iStorage.AnimateGraph(obj, _ => { // Move the selection to the parent node var parent = obj.ParentNode; iStorage.SelectedObject = parent; P.forEach(n => { iStorage.ChangeParent(n, newParent); }, childNodes); SystemEvents.AnnounceVisualScriptElementWillBeRemoved(obj); iStorage.DestroyInstance(obj.InstanceId); P.zipWith((n, p) => { n.LocalAnchorFromGlobalPosition = p; }, childNodes, childPos); iStorage.ForcedRelayoutOfTree(); } ); } catch (System.Exception) { CancelTransaction(iStorage); return; } CloseTransaction(iStorage, "Delete " + obj.DisplayName); }
// ---------------------------------------------------------------------- // Updates the global Rect arround the children nodes. It is assume that // the children have previously been layed out. The anchor position and // layout size will be updated accordingly. // NOTE: This function must not be called for iconized nodes. // ---------------------------------------------------------------------- // Revised: feb 10, 2014 public void WrapAroundChildrenNodes() { // Nothing to do if node is not visible. if (!IsVisibleInLayout || IsIconizedInLayout) { return; } if (IsFoldedInLayout) { var r = NodeRectFromChildrenRectWithMargins(new Rect(0, 0, 0, 0)); LocalSize = new Vector2(r.width, r.height); return; } var childNodes = BuildListOfVisibleChildNodes(n => !n.IsFloating); var childRects = P.map(n => n.LocalRect, childNodes); // WrapAroundChildRects(childRects); var totalChildRect = GetRectWithMargins(childRects); var parentRect = NodeRectFromChildrenRectWithMargins(totalChildRect); var center = PositionFrom(parentRect); WrappingOffset = center; LocalSize = SizeFrom(parentRect); // Restore child global position. for (int i = 0; i < childNodes.Length; ++i) { childNodes[i].CollisionOffset -= center; } }
// ================================================================================= /// Ask the user to provide the needed information to create a project. void CreatePackage() { // -- Header. -- ourHeaderTextStyle.normal.textColor = ourSelectedColor; GUI.Label(ourCreatePackageTextRect, ourCreatePackageText, ourHeaderTextStyle); // -- Project fields. -- myNewPackage.PackageName = EditorGUI.TextField(GetFieldPosition(0), "Package Name", myNewPackage.PackageName, ourTextFieldStyle); var allPackages = BuildPackageSelection(); var packageNames = P.map(p => p == null ? "-- None --" : p.PackageName, allPackages); myParentSelection = EditorGUI.Popup(GetFieldPosition(1), "Parent Package", myParentSelection, packageNames /*, ourPopupStyle*/); myNewPackage.ParentPackage = allPackages[myParentSelection]; EditorGUI.BeginDisabledGroup(true); EditorGUI.TextField(GetFieldPosition(3), "Package Folder", myNewPackage.GetRelativePackageFolder(), ourTextFieldStyle); EditorGUI.TextField(GetFieldPosition(4), "Engine Namespace", myNewPackage.GetEngineNamespace(), ourTextFieldStyle); EditorGUI.TextField(GetFieldPosition(5), "Editor Namespace", myNewPackage.GetEditorNamespace(), ourTextFieldStyle); EditorGUI.EndDisabledGroup(); // -- Compute button area. -- var totalWidth = ourListAreaRect.width; var width = totalWidth / 4f; var buttonWidth = width - kSpacer; var buttonXMax = ourListAreaRect.xMax; var buttonY = position.height - kSpacer - 20.0f; // -- Show project already exists error message. -- bool packageAlreadyExists = myNewPackage.AlreadyExists; if (packageAlreadyExists) { var x = buttonXMax - 2f * width; var y = buttonY - 60f; var w = 2f * width - kSpacer; var h = 40f; EditorGUI.HelpBox(new Rect(x, y, w, h), "PROJECT ALREADY EXISTS:\n--> " + myNewPackage.GetRelativeFileNamePath(), MessageType.Error); } // -- Process "Save" button. -- EditorGUI.BeginDisabledGroup(packageAlreadyExists); if (GUI.Button(new Rect(buttonXMax - width, buttonY, buttonWidth, 20.0f), "Save")) { if (!packageAlreadyExists) { myNewPackage.Save(); PackageController.UpdatePackageDatabase(); myMenuSelection = 0; } } EditorGUI.EndDisabledGroup(); // -- Process "Cancel" button. -- if (GUI.Button(new Rect(buttonXMax - 2f * width, buttonY, buttonWidth, 20.0f), "Cancel")) { myMenuSelection = 0; } }
// ---------------------------------------------------------------------- public static string[] FilterAndSort(string search, string[] lst, float minScore) { var scores = GetScores(search, lst); var ts = P.zip(scores, lst); var filtered = P.filter((t) => t.Item1 > minScore, ts); P.sort( filtered, (t1, t2) => { var diff = t2.Item1 - t1.Item1; return(Math3D.IsZero(diff) ? 0 : (diff < 0 ? -1 : 1)); } ); return(P.map((t) => P.uncurry((score, str) => str, t), filtered)); }
// ====================================================================== // Collision Functions // ---------------------------------------------------------------------- // Resolves the collision between children. "true" is returned if a // collision has occured. // ---------------------------------------------------------------------- public void ResolveCollisionOnChildrenNodes() { // Get a snapshot of the children state. var children = BuildListOfVisibleChildNodes(c => !c.IsFloating); var childPos = P.map(n => n.LocalAnchorPosition + n.WrappingOffset, children); var childRect = P.map(n => BuildRect(n.LocalAnchorPosition + n.WrappingOffset, n.LocalSize), children); // Resolve collisions. ResolveCollisionOnChildrenImp(children, ref childRect); // Update child position. for (int i = 0; i < P.length(children); ++i) { children[i].CollisionOffset = PositionFrom(childRect[i]) - childPos[i]; } }
// ---------------------------------------------------------------------- public static string[] SortAndTake(string search, string[] lst, int maxNbOfResults) { var scores = GetScores(search, lst); var toSort = P.zip(scores, lst); P.sort( toSort, (t1, t2) => { var diff = t2.Item1 - t1.Item1; return(Math3D.IsZero(diff) ? 0 : (diff < 0 ? -1 : 1)); } ); var result = P.take(maxNbOfResults, toSort); return(P.map((t) => P.uncurry((score, str) => str, t), result)); }
// ----------------------------------------------------------------------- /// Display the error/warning details inside the given area. /// /// @param r The area in which to display the error/warning details. /// @param errors The error details. /// @param warnings The warning details. /// public static void DisplayErrorAndWarningDetails(Rect r, List <ErrorWarning> errors, List <ErrorWarning> warnings) { // -- We must have at least one item to display -- var nbErrors = errors != null ? errors.Count : 0; var nbWarnings = warnings != null ? warnings.Count : 0; if (nbErrors == 0 && nbWarnings == 0) { return; } // -- convert ErrorWarning to their string representation -- string[] errorsStrings = null; string[] warningStrings = null; if (nbErrors != 0) { errorsStrings = P.map(e => e.Message, errors).ToArray(); } if (nbWarnings != 0) { warningStrings = P.map(w => w.Message, warnings).ToArray(); } DisplayErrorAndWarningDetails(r, errorsStrings, warningStrings); }
// ---------------------------------------------------------------------- /// Returns the members of type T installed on this type. /// /// @return The array of member <T> installed on this type. /// public T[] GetMembers <T>() where T : LibraryObject { var events = P.filter(p => p is T, children); return(P.map(p => p as T, events).ToArray()); }
// ---------------------------------------------------------------------- public static float[] GetScores(string search, string[] lst) { return(P.map(x => GetScore(search, x), lst)); }
// ---------------------------------------------------------------------- public static string[] SortAndTake_(string search, string[] lst, int maxNbOfResults = 0, float minScore = 0.5f) { // Define local sort function Action <P.Tuple <float, string>[]> sort = (ts) => { P.sort( ts, (t1, t2) => { var diff = t2.Item1 - t1.Item1; return(Math3D.IsZero(diff) ? 0 : (diff < 0 ? -1 : 1)); } ); }; // Correctly size result. var len = lst.Length; if (maxNbOfResults == 0) { maxNbOfResults = len; } if (maxNbOfResults > len) { maxNbOfResults = len; } var result = new P.Tuple <float, string> [maxNbOfResults]; int resultLen = 0; // Filter out the input list bool isSorted = false; foreach (var l in lst) { var score = GetScore(search, l); if (score <= minScore) { continue; } if (resultLen < maxNbOfResults) { result[resultLen] = P.curry(t => P.id(t), score, l); ++resultLen; if (resultLen == maxNbOfResults) { sort(result); isSorted = true; } } else { if (score > result[resultLen - 1].Item1) { result[resultLen - 1] = P.curry(t => P.id(t), score, l); sort(result); isSorted = true; } } // TODO: finish SortAndTake_ } // Perform a last sort in case we have not filled the max number of results. if (isSorted == false) { result = P.take(resultLen, result); sort(result); } return(P.map((t) => P.uncurry((score, str) => str, t), result)); }
// ================================================================================= /// Ask the user to provide the needed information to create a project. void Create() { // -- Label column -- var pos = GetLabelColumnPositions(6); GUI.Label(pos[0], "Package Name"); GUI.Label(pos[1], "Parent Package"); GUI.Label(pos[3], "Package Folder"); GUI.Label(pos[4], "Engine Namespace"); GUI.Label(pos[5], "Editor Namespace"); // -- Value column -- pos = GetValueColumnPositions(6); myProject.PackageName = EditorGUI.TextField(pos[0], myProject.PackageName); var allPackages = BuildPackageSelection(); var packageNames = P.map(p => p == null ? "-- None --" : p.PackageName, allPackages); myParentSelection = EditorGUI.Popup(pos[1], myParentSelection, packageNames); myProject.ParentPackage = allPackages[myParentSelection]; EditorGUI.BeginDisabledGroup(true); EditorGUI.TextField(pos[3], myProject.GetRelativePackageFolder()); EditorGUI.TextField(pos[4], myProject.GetEngineNamespace()); EditorGUI.TextField(pos[5], myProject.GetEditorNamespace()); EditorGUI.EndDisabledGroup(); // -- Compute button area. -- var totalWidth = kColumn2Width + kColumn3Width; var width = totalWidth / 3f; var buttonWidth = width - 2f * kMargin; var buttonX = kColumn2X + 2 * kMargin; var buttonY = position.height - kMargin - 20.0f; // -- Show project already exists error message. -- bool projectAlreadyExists = myProject.AlreadyExists; if (projectAlreadyExists) { var x = buttonX - kMargin; var y = buttonY - 3f * pos[0].height; var w = totalWidth; var h = 2f * pos[0].height; EditorGUI.HelpBox(new Rect(x, y, w, h), "PROJECT ALREADY EXISTS:\n--> " + myProject.GetRelativeFileNamePath(), MessageType.Error); } // -- Process "Save" button. -- EditorGUI.BeginDisabledGroup(projectAlreadyExists); if (GUI.Button(new Rect(buttonX + width, buttonY, buttonWidth, 20.0f), "Save")) { if (!projectAlreadyExists) { myProject.Save(); PackageController.UpdatePackageDatabase(); Close(); } } EditorGUI.EndDisabledGroup(); // -- Process "Cancel" button. -- if (GUI.Button(new Rect(buttonX + 2f * width, buttonY, buttonWidth, 20.0f), "Cancel")) { Close(); } }
// ------------------------------------------------------------------------- /// Builds of list of conditional contexts associated with the list of /// function calls. /// /// @param funcCalls List of function calls. /// @return List of conditional context associated with the list of function /// calls. /// iCS_EditorObject[][] GetConditionalContexts(iCS_EditorObject[] funcCalls) { return(P.map(fc => ControlFlow.GetAllRelatedEnablePorts(fc), funcCalls)); }