Skip to content

Commit c42d1f6

Browse files
authored
Handle parent directory renaming whilst asset is being edited. (#1049)
* Added test to ensure that an exception is not thrown when Saving input asset and the parent directory was renamed. (case 1207527) * Removed cached asset path. We now use the asset guid to get the path when requested. (case 1207527) When the parent directory is renamed the path becomes invalid. Its much safer to use the asset guid and resolve the path when its requested. There is no continuous use of the path in code so it should not have any performance impact. * Code Formatting * Discard the unused argument. Fixes a warning. * Ignore warning CA1801 * Test the file has been modified instead of an exception not being thrown. We should test for the behaviour we actually want. * Added CHANGELOG entry * Use the [Unreleased] header instead of a unreleased version and date
1 parent 32b13c3 commit c42d1f6

File tree

4 files changed

+56
-19
lines changed

4 files changed

+56
-19
lines changed

Assets/Tests/InputSystem/CoreTests_Editor.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,36 @@ public void Editor_InputAsset_CanReplaceBindingGroupThroughSerialization()
545545
Assert.That(map.bindings[0].groups, Is.EqualTo(""));
546546
}
547547

548+
[Test]
549+
[Category("Editor")]
550+
public void Editor_InputActionAssetManager_CanMoveAssetOnDisk()
551+
{
552+
const string kAssetPath = "Assets/DirectoryBeforeRename/InputAsset." + InputActionAsset.Extension;
553+
const string kAssetPathAfterMove = "Assets/DirectoryAfterRename/InputAsset." + InputActionAsset.Extension;
554+
const string kDefaultContents = "{}";
555+
556+
AssetDatabase.CreateFolder("Assets", "DirectoryBeforeRename");
557+
File.WriteAllText(kAssetPath, kDefaultContents);
558+
AssetDatabase.ImportAsset(kAssetPath);
559+
560+
var asset = AssetDatabase.LoadAssetAtPath<InputActionAsset>(kAssetPath);
561+
Assert.NotNull(asset, "Could not load asset: " + kAssetPath);
562+
563+
var inputActionAssetManager = new InputActionAssetManager(asset);
564+
inputActionAssetManager.Initialize();
565+
inputActionAssetManager.onDirtyChanged = (bool dirty) => {};
566+
567+
FileUtil.MoveFileOrDirectory("Assets/DirectoryBeforeRename", "Assets/DirectoryAfterRename");
568+
AssetDatabase.Refresh();
569+
570+
Assert.DoesNotThrow(() => inputActionAssetManager.SaveChangesToAsset());
571+
572+
var fileContents = File.ReadAllText(kAssetPathAfterMove);
573+
Assert.AreNotEqual(kDefaultContents, fileContents, "Expected file contents to have been modified after SaveChangesToAsset was called.");
574+
575+
AssetDatabase.DeleteAsset("Assets/DirectoryAfterRename");
576+
}
577+
548578
private class MonoBehaviourWithEmbeddedAction : MonoBehaviour
549579
{
550580
public InputAction action;

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77
Due to package verification, the latest version below is the unpublished version and the date is meaningless.
88
however, it has to be formatted properly to pass verification tests.
99

10-
## [1.0.0-preview.5] - 2020-12-12
10+
## [Unreleased]
1111

1212
### Changed
1313

@@ -19,6 +19,7 @@ however, it has to be formatted properly to pass verification tests.
1919
- XR controllers and HMDs have proper display names in the UI again. This regressed in preview.4 such that all XR controllers were displayed as just "XR Controller" in the UI and all HMDs were displayed as "XR HMD".
2020
- `InputSystemUIInputModule` no longer generates GC heap garbage every time mouse events are processed.
2121
- Fixed a bug where an internal array helper method was corrupting array contents leading to bugs in both `InputUser` and `Touch`.
22+
- Fixed exception when saving changes to an Input Action asset and the parent directory has been renamed. ([case 1207527](https://issuetracker.unity3d.com/issues/input-system-console-errors-appear-when-you-save-input-action-asset-after-changing-the-name-of-the-folder-containing-it))
2223

2324
#### Actions
2425

Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionAssetManager.cs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,24 @@ internal class InputActionAssetManager : IDisposable
1515
[SerializeField] internal InputActionAsset m_AssetObjectForEditing;
1616
[SerializeField] private InputActionAsset m_ImportedAssetObject;
1717
[SerializeField] private string m_AssetGUID;
18-
[SerializeField] private string m_AssetPath;
1918
[SerializeField] private string m_ImportedAssetJson;
2019
[SerializeField] private bool m_IsDirty;
2120

2221
private SerializedObject m_SerializedObject;
2322

2423
public string guid => m_AssetGUID;
2524

26-
public string path { get => m_AssetPath; set => m_AssetPath = value; }
25+
public string path
26+
{
27+
get
28+
{
29+
Debug.Assert(!string.IsNullOrEmpty(m_AssetGUID), "Asset GUID is empty");
30+
var assetPath = AssetDatabase.GUIDToAssetPath(m_AssetGUID);
31+
if (string.IsNullOrEmpty(assetPath))
32+
throw new InvalidOperationException("Could not determine asset path for " + m_AssetGUID);
33+
return assetPath;
34+
}
35+
}
2736

2837
public string name
2938
{
@@ -32,8 +41,8 @@ public string name
3241
if (m_ImportedAssetObject != null)
3342
return m_ImportedAssetObject.name;
3443

35-
if (!string.IsNullOrEmpty(m_AssetPath))
36-
return Path.GetFileNameWithoutExtension(m_AssetPath);
44+
if (!string.IsNullOrEmpty(path))
45+
return Path.GetFileNameWithoutExtension(path);
3746

3847
return string.Empty;
3948
}
@@ -55,8 +64,7 @@ private InputActionAsset importedAsset
5564
public InputActionAssetManager(InputActionAsset inputActionAsset)
5665
{
5766
m_ImportedAssetObject = inputActionAsset;
58-
m_AssetPath = AssetDatabase.GetAssetPath(importedAsset);
59-
m_AssetGUID = AssetDatabase.AssetPathToGUID(m_AssetPath);
67+
Debug.Assert(AssetDatabase.TryGetGUIDAndLocalFileIdentifier(importedAsset, out m_AssetGUID, out long _), $"Failed to get asset {inputActionAsset.name} GUID");
6068
}
6169

6270
public SerializedObject serializedObject => m_SerializedObject;
@@ -123,13 +131,7 @@ public void Cleanup()
123131

124132
public void LoadImportedObjectFromGuid()
125133
{
126-
Debug.Assert(!string.IsNullOrEmpty(m_AssetGUID));
127-
128-
m_AssetPath = AssetDatabase.GUIDToAssetPath(m_AssetGUID);
129-
if (string.IsNullOrEmpty(m_AssetPath))
130-
throw new InvalidOperationException("Could not determine asset path for " + m_AssetGUID);
131-
132-
m_ImportedAssetObject = AssetDatabase.LoadAssetAtPath<InputActionAsset>(m_AssetPath);
134+
m_ImportedAssetObject = AssetDatabase.LoadAssetAtPath<InputActionAsset>(path);
133135
}
134136

135137
public void ApplyChanges()
@@ -140,19 +142,20 @@ public void ApplyChanges()
140142

141143
internal void SaveChangesToAsset()
142144
{
143-
Debug.Assert(!string.IsNullOrEmpty(m_AssetPath));
145+
Debug.Assert(importedAsset != null);
144146

145147
// Update JSON.
146148
var asset = m_AssetObjectForEditing;
147149
m_ImportedAssetJson = asset.ToJson();
148150

149151
// Write out, if changed.
150-
var existingJson = File.ReadAllText(m_AssetPath);
152+
var assetPath = path;
153+
var existingJson = File.ReadAllText(assetPath);
151154
if (m_ImportedAssetJson != existingJson)
152155
{
153156
////TODO: has to be made to work with version control
154-
File.WriteAllText(m_AssetPath, m_ImportedAssetJson);
155-
AssetDatabase.ImportAsset(m_AssetPath);
157+
File.WriteAllText(assetPath, m_ImportedAssetJson);
158+
AssetDatabase.ImportAsset(assetPath);
156159
}
157160

158161
m_IsDirty = false;

Packages/com.unity.inputsystem/InputSystem/Editor/AssetEditor/InputActionEditorWindow.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,8 @@ public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOption
825825
return default;
826826
}
827827

828+
#pragma warning disable CA1801 // unused parameters
829+
828830
// Handle .inputactions asset being moved.
829831
// ReSharper disable once UnusedMember.Local
830832
public static AssetMoveResult OnWillMoveAsset(string sourcePath, string destinationPath)
@@ -836,12 +838,13 @@ public static AssetMoveResult OnWillMoveAsset(string sourcePath, string destinat
836838
var window = FindEditorForAssetWithGUID(guid);
837839
if (window != null)
838840
{
839-
window.m_ActionAssetManager.path = destinationPath;
840841
window.UpdateWindowTitle();
841842
}
842843

843844
return default;
844845
}
846+
847+
#pragma warning restore CA1801
845848
}
846849
}
847850
}

0 commit comments

Comments
 (0)