Skip to content

Commit a1a42e2

Browse files
committed
Merge branch 'master' into UNI-32844-export-animation-only
2 parents 1b2f9e0 + a9baf82 commit a1a42e2

File tree

6 files changed

+184
-15
lines changed

6 files changed

+184
-15
lines changed

Assets/FbxExporters/Editor/FbxExporter.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ public static HashSet<float> GetSampleTimes(AnimationCurve[] animCurves, double
13731373
var keyTimes = new HashSet<float>();
13741374
double fs = 1.0/sampleRate;
13751375

1376-
double currSample = double.MaxValue, firstTime = double.MaxValue, lastTime = double.MinValue;
1376+
double firstTime = double.MaxValue, lastTime = double.MinValue;
13771377

13781378
foreach (var ac in animCurves)
13791379
{
@@ -1383,9 +1383,10 @@ public static HashSet<float> GetSampleTimes(AnimationCurve[] animCurves, double
13831383
lastTime = System.Math.Max(lastTime, ac[ac.length-1].time);
13841384
}
13851385

1386-
for (currSample = firstTime; currSample < lastTime; currSample += fs)
1387-
{
1388-
keyTimes.Add((float)currSample);
1386+
int firstframe = (int)(firstTime * sampleRate);
1387+
int lastframe = (int)(lastTime * sampleRate);
1388+
for (int i = firstframe; i <= lastframe; i++) {
1389+
keyTimes.Add ((float)(i * fs));
13891390
}
13901391

13911392
return keyTimes;
@@ -2952,7 +2953,7 @@ static void OnContextItem (MenuCommand command)
29522953
}
29532954

29542955
/// <summary>
2955-
// Validate the menu item defined by the function above.
2956+
/// Validate the menu item defined by the function above.
29562957
/// </summary>
29572958
[MenuItem (MenuItemName, true, 30)]
29582959
public static bool OnValidateMenuItem ()
@@ -2990,6 +2991,7 @@ public static void DisplayNoSelectionDialog()
29902991
"No GameObjects selected for export.",
29912992
"Ok");
29922993
}
2994+
29932995
//
29942996
// export mesh info from Unity
29952997
//

Assets/FbxExporters/Editor/FbxPrefabAutoUpdater.cs

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using UnityEditor;
66
using System.Linq;
77
using System;
8+
using FbxExporters.Editor;
9+
using UnityEngine.TestTools;
810

911
namespace FbxExporters
1012
{
@@ -30,14 +32,18 @@ namespace FbxExporters
3032
#else
3133
public const string FBX_PREFAB_FILE = "/UnityFbxPrefab.dll";
3234
#endif
35+
36+
const string MenuItemName = "GameObject/Update from FBX";
37+
public static bool runningUnitTest = false;
38+
3339
public static string FindFbxPrefabAssetPath()
3440
{
3541
// Find guids that are scripts that look like FbxPrefab.
3642
// That catches FbxPrefabTest too, so we have to make sure.
3743
var allGuids = AssetDatabase.FindAssets("FbxPrefab t:MonoScript");
38-
foreach(var guid in allGuids) {
44+
foreach (var guid in allGuids) {
3945
var path = AssetDatabase.GUIDToAssetPath(guid);
40-
if (path.EndsWith (FBX_PREFAB_FILE)) {
46+
if (path.EndsWith(FBX_PREFAB_FILE)) {
4147
return path;
4248
}
4349
}
@@ -65,7 +71,7 @@ public static bool MayHaveFbxPrefabToFbxAsset(string prefabPath,
6571
var depPaths = AssetDatabase.GetDependencies(prefabPath, recursive: false);
6672
bool dependsOnFbxPrefab = false;
6773
bool dependsOnImportedFbx = false;
68-
foreach(var dep in depPaths) {
74+
foreach (var dep in depPaths) {
6975
if (dep == fbxPrefabScriptPath) {
7076
if (dependsOnImportedFbx) { return true; }
7177
dependsOnFbxPrefab = true;
@@ -79,7 +85,7 @@ public static bool MayHaveFbxPrefabToFbxAsset(string prefabPath,
7985
return false;
8086
}
8187

82-
static void OnPostprocessAllAssets(string [] imported, string [] deleted, string [] moved, string [] movedFrom)
88+
static void OnPostprocessAllAssets(string[] imported, string[] deleted, string[] moved, string[] movedFrom)
8389
{
8490
// Do not start if Auto Updater is disabled in FBX Exporter Settings
8591
if (!FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled)
@@ -92,9 +98,12 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
9298
// Did we import an fbx file at all?
9399
// Optimize to not allocate in the common case of 'no'
94100
HashSet<string> fbxImported = null;
95-
foreach(var fbxModel in imported) {
101+
foreach (var fbxModel in imported) {
96102
if (IsFbxAsset(fbxModel)) {
97-
if (fbxImported == null) { fbxImported = new HashSet<string>(); }
103+
if (fbxImported == null)
104+
{
105+
fbxImported = new HashSet<string>();
106+
}
98107
fbxImported.Add(fbxModel);
99108
//Debug.Log("Tracking fbx asset " + fbxModel);
100109
} else {
@@ -116,7 +125,7 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
116125
//
117126
var fbxPrefabScriptPath = FindFbxPrefabAssetPath();
118127
var allObjectGuids = AssetDatabase.FindAssets("t:GameObject");
119-
foreach(var guid in allObjectGuids) {
128+
foreach (var guid in allObjectGuids) {
120129
var prefabPath = AssetDatabase.GUIDToAssetPath(guid);
121130
if (!IsPrefabAsset(prefabPath)) {
122131
//Debug.Log("Not a prefab: " + prefabPath);
@@ -140,8 +149,8 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
140149
//Debug.LogWarning("FbxPrefab reimport: failed to update prefab " + prefabPath);
141150
continue;
142151
}
143-
foreach(var fbxPrefabComponent in prefab.GetComponentsInChildren<FbxPrefab>()) {
144-
var fbxPrefabUtility = new FbxPrefabUtility (fbxPrefabComponent);
152+
foreach (var fbxPrefabComponent in prefab.GetComponentsInChildren<FbxPrefab>()) {
153+
var fbxPrefabUtility = new FbxPrefabUtility(fbxPrefabComponent);
145154
if (!fbxPrefabUtility.WantsAutoUpdate()) {
146155
//Debug.Log("Not auto-updating " + prefabPath);
147156
continue;
@@ -156,8 +165,89 @@ static void OnPostprocessAllAssets(string [] imported, string [] deleted, string
156165
}
157166
}
158167
}
168+
/// <summary>
169+
/// Add an option "Update from FBX" in the contextual GameObject menu.
170+
/// </summary>
171+
[MenuItem(MenuItemName, false,31)]
172+
static void OnContextItem(MenuCommand command)
173+
{
174+
GameObject[] selection = null;
175+
176+
if (command == null || command.context == null)
177+
{
178+
// We were actually invoked from the top GameObject menu, so use the selection.
179+
selection = Selection.GetFiltered<GameObject>(SelectionMode.Editable | SelectionMode.TopLevel);
180+
}
181+
else
182+
{
183+
// We were invoked from the right-click menu, so use the context of the context menu.
184+
var selected = command.context as GameObject;
185+
if (selected)
186+
{
187+
selection = new GameObject[] { selected };
188+
}
189+
}
190+
191+
foreach (GameObject selectedObject in selection)
192+
{
193+
UpdateLinkedPrefab(selectedObject);
194+
}
195+
}
196+
197+
/// <summary>
198+
/// Validate the menu item defined by the function above.
199+
/// </summary>
200+
[MenuItem(MenuItemName, true,31)]
201+
public static bool OnValidateMenuItem()
202+
{
203+
GameObject[] selection = Selection.gameObjects;
204+
205+
if (selection == null || selection.Length == 0)
206+
{
207+
return false;
208+
}
209+
210+
bool containsLinkedPrefab = false;
211+
foreach (GameObject selectedObject in selection)
212+
{
213+
GameObject prefab = UnityEditor.PrefabUtility.GetPrefabParent(selectedObject) as GameObject;
214+
if (prefab && prefab.GetComponentInChildren<FbxPrefab>())
215+
{
216+
containsLinkedPrefab = true;
217+
break;
218+
}
219+
}
220+
221+
return containsLinkedPrefab;
222+
}
159223

160224

225+
static void DisplayNoSelectionDialog(string message)
226+
{
227+
UnityEditor.EditorUtility.DisplayDialog(
228+
string.Format("{0} Warning", ModelExporter.PACKAGE_UI_NAME),
229+
message,
230+
"Ok");
231+
}
232+
233+
/// <summary>
234+
/// Launch the manual update of the linked prefab specified
235+
/// </summary>
236+
public static void UpdateLinkedPrefab(GameObject prefabInstance)
237+
{
238+
GameObject prefab = UnityEditor.PrefabUtility.GetPrefabParent(prefabInstance) as GameObject;
239+
if (!prefab)
240+
{
241+
return;
242+
}
243+
244+
foreach (var fbxPrefabComponent in prefab.GetComponentsInChildren<FbxPrefab>())
245+
{
246+
var fbxPrefabUtility = new FbxPrefabUtility(fbxPrefabComponent);
247+
fbxPrefabUtility.SyncPrefab();
248+
}
249+
}
250+
161251
public class FbxPrefabUtility{
162252

163253
private FbxPrefab m_fbxPrefab;

Assets/FbxExporters/Editor/UnitTests/FbxPrefabAutoUpdaterTest.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,10 @@ public class FbxPrefabAutoUpdaterToggleTest : ExporterTestBase
215215
[SetUp]
216216
public void Init()
217217
{
218+
// Save the initial setting for the auto updater toggle and disable it for the unit test
218219
isAutoUpdaterOn = FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled;
219220
FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled = false;
221+
FbxPrefabAutoUpdater.runningUnitTest = true;
220222
}
221223

222224
[Test]
@@ -265,13 +267,58 @@ public void RemappingTest()
265267
Assert.IsTrue(cubePrefabInstance.GetComponent<MeshFilter>().sharedMesh != null);
266268
Assert.IsTrue(cubePrefabInstance.transform.GetChild(0).name == "Sphere");
267269
Assert.IsTrue(cubePrefabInstance.transform.GetChild(0).GetComponent<MeshFilter>().sharedMesh != null);
270+
271+
// Testing Manual update on true prefab
272+
GameObject[] selection = new GameObject[] { cubePrefabInstance };
273+
FbxPrefabAutoUpdater.UpdateLinkedPrefab(selection[0]);
274+
Assert.IsTrue(cubePrefabInstance != null);
275+
Assert.IsTrue(cubePrefabInstance.GetComponent<MeshFilter>().sharedMesh != null);
276+
Assert.IsTrue(cubePrefabInstance.transform.GetChild(0).name == "SphereFBX");
277+
Assert.IsTrue(cubePrefabInstance.transform.GetChild(0).GetComponent<MeshFilter>().sharedMesh != null);
278+
279+
// Testing Manual update on some random object that isn't a prefab at all, the gameobject shouldn't be modified. No error is returned
280+
GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
281+
FbxPrefabAutoUpdater.UpdateLinkedPrefab(quad);
282+
Assert.IsTrue(quad != null);
283+
Assert.IsTrue(quad.GetComponent<MeshFilter>().sharedMesh != null);
284+
285+
// Testing Manual update on some random prefab that doesn't have an FbxPrefab in it, the prefab shouldn't be modified. No error is returned
286+
GameObject capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule);
287+
// Convert to linked prefab instance (auto-updating prefab)
288+
string prefabPath = GetRandomPrefabAssetPath();
289+
GameObject capsuleInstance = PrefabUtility.CreatePrefab(prefabPath, capsule);
290+
FbxPrefabAutoUpdater.UpdateLinkedPrefab(capsuleInstance);
291+
Assert.IsTrue(capsuleInstance != null);
292+
Assert.IsTrue(capsuleInstance.GetComponent<MeshFilter>().sharedMesh != null);
293+
294+
// Check the menu returns true because sphere3 is a linked prefab
295+
GameObject cylinder3 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
296+
GameObject sphere3 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
297+
sphere3.transform.SetParent(cylinder3.transform);
298+
GameObject sphere3Instance = ConvertToModel.Convert(sphere3, fbxFullPath: filePath);
299+
Selection.objects = new GameObject[] { sphere3Instance };
300+
Assert.IsTrue(FbxPrefabAutoUpdater.OnValidateMenuItem());
301+
302+
// Check the contextual menu returns false because there is no linked prefab in the selection, an error is returned
303+
GameObject cylinder4 = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
304+
GameObject sphere4 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
305+
sphere4.transform.SetParent(cylinder4.transform);
306+
Selection.objects = new GameObject[] { cylinder4, sphere4 };
307+
Assert.IsFalse(FbxPrefabAutoUpdater.OnValidateMenuItem());
308+
309+
// Assert is true because sphere 3 instance is a linked prefab and all the selection is taken into account
310+
sphere3Instance.transform.SetParent(quad.transform);
311+
Selection.objects = new GameObject[] { quad, sphere3Instance };
312+
Assert.IsTrue(FbxPrefabAutoUpdater.OnValidateMenuItem());
268313
}
269314

270315

271316
[TearDown]
272317
public void stopTest()
273318
{
319+
// Put back the initial setting for the auto-updater toggle
274320
FbxExporters.EditorTools.ExportSettings.instance.autoUpdaterEnabled = isAutoUpdaterOn;
321+
FbxPrefabAutoUpdater.runningUnitTest = false;
275322
}
276323
}
277324
}

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ endif()
2323
message(STATUS "Building for ${CMAKE_BUILD_TYPE}")
2424

2525
if (NOT DEFINED PACKAGE_VERSION OR "${PACKAGE_VERSION}" STREQUAL "")
26-
set(PACKAGE_VERSION "sprint43")
26+
set(PACKAGE_VERSION "1.3.0a1")
2727
endif()
2828
message(STATUS "Using Package Version: ${PACKAGE_VERSION}")
2929

@@ -259,3 +259,4 @@ endif()
259259
install(DIRECTORY ${CMAKE_SOURCE_DIR}/meta/FbxExporters
260260
DESTINATION .)
261261
install(FILES "${CMAKE_SOURCE_DIR}/meta/FbxExporters.meta" DESTINATION .)
262+
install(FILES "${CMAKE_SOURCE_DIR}/RELEASE_NOTES_EXTERNAL.md" DESTINATION FbxExporters RENAME "RELEASE_NOTES.txt")

RELEASE_NOTES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
RELEASE NOTES
22

3+
**Version**: 1.3.0a1
4+
5+
FIXES
6+
* FbxExporter: fixed so last keyframe is exported
7+
* fix Universal Windows Platform build errors
8+
9+
Error caused by UnityFbxSdk.dll being set as compatible with any platform instead of editor only.
10+
311
**Version**: sprint43
412

513
NEW FEATURES

RELEASE_NOTES_EXTERNAL.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
RELEASE NOTES
2+
3+
**Version**: 1.3.0a1
4+
5+
NEW FEATURES
6+
* FbxExporter: Added support for exporting Blendshapes
7+
* FbxExporter: Added support for exporting SkinnedMeshes with legacy and generic animation
8+
* FbxExporter: Added support for exporting Lights with animatable properties (Intensity, Spot Angle, Color)
9+
* FbxExporter: Added support for exporting Cameras with animatable properties (Field of View)
10+
* FbxExporter: added ability to export animation on transforms
11+
12+
FIXES
13+
* fix Universal Windows Platform build errors
14+
15+
Error caused by UnityFbxSdk.dll being set as compatible with any platform instead of editor only.
16+
17+
**Version**: 1.2.0b1
18+
19+
**Version**: 1.1.0b1
20+
21+
**Version**: 1.0.0b1

0 commit comments

Comments
 (0)