-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ut 148/downcast fbx objects #302
base: main
Are you sure you want to change the base?
Changes from all commits
a9af8e6
8240ba6
858eddb
1b45a3e
300adbf
e5b0665
0ec4bcd
7fafafa
907e1da
c6bbdfb
ec0b554
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// *********************************************************************** | ||
// Copyright (c) 2017 Unity Technologies. All rights reserved. | ||
// | ||
// Licensed under the ##LICENSENAME##. | ||
// See LICENSE.md file in the project root for full license information. | ||
// *********************************************************************** | ||
|
||
%rename("%s", %$isclass) FbxClassId; | ||
// %rename("%s", %$isclass) FbxClassIdInfo* ; | ||
|
||
%rename("%s") FbxClassId::FbxClassId; | ||
%rename("%s") FbxClassId::Create; | ||
%rename("%s") FbxClassId::Is; | ||
%rename("%s") FbxClassId::GetName; | ||
%rename("%s") FbxClassId::IsValid; | ||
%rename("%s") FbxClassId::GetParent; | ||
|
||
|
||
// also IS, getName, and others. | ||
%include "fbxsdk/core/fbxclassid.h" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#! /usr/bin/python | ||
|
||
# *********************************************************************** | ||
# Copyright (c) 2017 Unity Technologies. All rights reserved. | ||
# | ||
# Licensed under the ##LICENSENAME##. | ||
# See LICENSE.md file in the project root for full license information. | ||
# *********************************************************************** | ||
|
||
import sys | ||
import re | ||
|
||
# Input: | ||
# 1- the output .i file | ||
# 2- the file that is the result of swig -debug-typedef | ||
# Output: | ||
# - a swig .i file to be %included at the start of the fbxsdk.i file | ||
|
||
# This should normally be integrated as part of the build system. | ||
output_filename = sys.argv[1] | ||
typedefs_filename = sys.argv[2] | ||
|
||
rootclass = "FbxObject" | ||
|
||
# For each derived class, a list of classes it inherits from. If a class isn't | ||
# in this dict it's not a derived class (it inherits from nothing). | ||
baseclasses = dict() | ||
|
||
def fix_classname(clsname): | ||
""" | ||
Template arguments get wrapped in parens for some reason. | ||
""" | ||
return re.sub(r'<\(', '<', re.sub(r'\)>', '>', clsname)) | ||
|
||
with open(typedefs_filename) as typedef_file: | ||
current_scope = None | ||
bases = [] | ||
def store(): | ||
if current_scope and bases: | ||
baseclasses[current_scope] = bases | ||
for line in typedef_file: | ||
m = re.search("Type scope '(.*)'", line) | ||
if m: | ||
# changing scope; store the old one, clear the accumulating list | ||
store() | ||
current_scope = fix_classname(m.group(1)) | ||
bases = [] | ||
m = re.search("Inherits from '(.*)'", line) | ||
if m: | ||
bases.append(fix_classname(m.group(1))) | ||
# end of file; remember the last block we read | ||
if current_scope and bases: | ||
store() | ||
|
||
# Find all the classes that derive from FbxObject. | ||
handleclasses = set() | ||
|
||
handleclasses.add(rootclass) | ||
for cls in baseclasses: | ||
# squash a warning about %extend, which happens when you | ||
# declare a typedef to a root class | ||
if cls.endswith('::ParentClass'): continue | ||
if rootclass in baseclasses[cls]: | ||
handleclasses.add(cls) | ||
|
||
leafclasses = set() | ||
allbases = [] | ||
# for klass in handleclasses: | ||
# import pprint as pp | ||
for klass in handleclasses: | ||
allbases += baseclasses[klass] | ||
allbases = set(allbases) | ||
for klass in handleclasses: | ||
if klass not in allbases: | ||
leafclasses.add(klass) | ||
nonleafclasses = handleclasses - leafclasses | ||
|
||
|
||
|
||
statement_start = """ | ||
private static System.Collections.Generic.Dictionary<System.IntPtr, int> ptrToIndexDict = new System.Collections.Generic.Dictionary<System.IntPtr, int>(); | ||
public static FbxObject Realtype (System.IntPtr cPtr, bool ignored) | ||
{ | ||
if (cPtr == System.IntPtr.Zero) | ||
{ | ||
return null; | ||
} | ||
|
||
System.IntPtr p = NativeMethods.FbxObject_GetRuntimeClassId(new System.Runtime.InteropServices.HandleRef(null, cPtr)); | ||
string name = NativeMethods.FbxClassId_GetName(new System.Runtime.InteropServices.HandleRef(null, p)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3 memory allocations per downcast... Let's optimize this on Monday. |
||
// This switch statement is auto-generated by a script | ||
switch (name) | ||
{""" | ||
|
||
statement_body_template = """ | ||
case "{}": | ||
return new {}(cPtr, ignored);""" | ||
|
||
statement_end = """ | ||
default: | ||
break; | ||
} | ||
// we failed to get a match, return a bland FbxObject. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I take it the TODO is to repeat the switch but on the parent class? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, I have a prototype that has not yet been committed. |
||
return new FbxObject(cPtr, ignored); | ||
} | ||
""" | ||
|
||
typemap_template = """ | ||
%typemap(csout, excode=SWIGEXCODE) {} {{ | ||
System.IntPtr cPtr = $imcall; | ||
$csclassname ret = ($csclassname) NativeMethods.Realtype(cPtr, $owner);$excode; | ||
return ret; | ||
}} | ||
""" | ||
|
||
body_statements = [statement_body_template.format(klass, klass) for klass in handleclasses] | ||
constructor_func = statement_start + ''.join(body_statements) + statement_end | ||
|
||
# write out the code | ||
with open(output_filename, 'w') as outfile: | ||
outfile.write("/*This code has been generated by the generate-downcast-table.py build script*/\n") | ||
outfile.write("%pragma(csharp) imclasscode=%{\n") | ||
outfile.write(constructor_func) | ||
outfile.write("%}\n") | ||
# the last type in the list also needs the pointer type qualifier | ||
typemap_list = "*, \n".join(nonleafclasses) + '*' | ||
outfile.write(typemap_template.format(typemap_list)) | ||
|
||
print("Generated downcast table for {} classes.".format(len(handleclasses))) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// *********************************************************************** | ||
// Copyright (c) 2017 Unity Technologies. All rights reserved. | ||
// | ||
// Licensed under the ##LICENSENAME##. | ||
// See LICENSE.md file in the project root for full license information. | ||
// *********************************************************************** | ||
using NUnit.Framework; | ||
using Autodesk.Fbx; | ||
using System.IO; | ||
|
||
|
||
|
||
namespace Autodesk.Fbx.UseCaseTests | ||
{ | ||
public class DowncastFbxType | ||
{ | ||
[Test] | ||
public void TestDowncast () | ||
{ | ||
using(FbxManager man = FbxManager.Create()) | ||
{ | ||
FbxMesh m = FbxMesh.Create(man, "some mesh"); | ||
FbxSkin s = FbxSkin.Create(man, "some deformer skin"); | ||
int index = m.AddDeformer(s); | ||
// FbxSkin o = m.GetDeformer(index) as FbxSkin; | ||
FbxSkin o = (FbxSkin)m.GetDeformer(index); | ||
Assert.That(o, Is.Not.Null); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestWeirdCase() | ||
{ | ||
string constraintName = "sdkjhsdkjhfkjsdhfjks"; | ||
string fileName = "bobobo.fbx"; | ||
string meshName = "some mesh"; | ||
string skinName = "some skin"; | ||
int index = 0; | ||
using(FbxManager manager = FbxManager.Create()) | ||
{ | ||
using (FbxExporter exporter = FbxExporter.Create (manager, "myExporter")) | ||
{ | ||
var format = manager.GetIOPluginRegistry().FindWriterIDByDescription("FBX ascii (*.fbx)"); | ||
// Initialize the exporter. | ||
bool status = exporter.Initialize (fileName, format, manager.GetIOSettings ()); | ||
|
||
// Create a scene with a single node that has an animation clip | ||
// attached to it | ||
FbxScene scene = FbxScene.Create(manager, "myScene"); | ||
|
||
FbxNode sourceNode = FbxNode.Create(scene, "source"); | ||
FbxNode constrainedNode = FbxNode.Create(scene, "constrained"); | ||
|
||
scene.GetRootNode().AddChild(sourceNode); | ||
scene.GetRootNode().AddChild(constrainedNode); | ||
|
||
FbxMesh m = FbxMesh.Create(manager, meshName); | ||
FbxSkin s = FbxSkin.Create(manager, skinName); | ||
index = m.AddDeformer(s); | ||
scene.AddMember(m); | ||
scene.AddMember(s); | ||
|
||
// FbxConstraint posConstraint = CreatePositionConstraint(scene, sourceNode, constrainedNode); | ||
FbxConstraintPosition constraint = FbxConstraintPosition.Create(scene, constraintName); | ||
|
||
constraint.SetConstrainedObject(constrainedNode); | ||
constraint.AddConstraintSource(sourceNode); | ||
|
||
constraint.AffectX.Set(true); | ||
constraint.AffectY.Set(true); | ||
constraint.AffectZ.Set(true); | ||
|
||
constraint.Translation.Set(new FbxDouble3(1, 2, 3)); | ||
|
||
Assert.That(constraint, Is.Not.Null); | ||
|
||
bool result = constraint.ConnectDstObject(scene); | ||
Assert.That(result, Is.True); | ||
|
||
// export the scene | ||
exporter.Export(scene); | ||
} | ||
FbxScene importedScene = null; | ||
// FbxMesh importedMesh = null; | ||
using (FbxImporter importer = FbxImporter.Create (manager, "myImporter")) | ||
{ | ||
|
||
// Initialize the importer. | ||
bool status = importer.Initialize (fileName, -1, manager.GetIOSettings ()); | ||
|
||
Assert.IsTrue (status); | ||
|
||
// Create a new scene so it can be populated by the imported file. | ||
importedScene = FbxScene.Create (manager, "myScene"); | ||
|
||
// Import the contents of the file into the scene. | ||
importer.Import (importedScene); | ||
} | ||
FbxMesh importedMesh = (FbxMesh)importedScene.FindMemberObject(meshName); | ||
Assert.That(importedMesh, Is.Not.Null); | ||
FbxSkin importedSkin = (FbxSkin)importedScene.FindMemberObject(skinName); | ||
Assert.That(importedSkin, Is.Not.Null); | ||
FbxNode importSourceNode = importedScene.GetRootNode().GetChild(0); | ||
FbxNode importConstrainedNode = importedScene.GetRootNode().GetChild(1); | ||
FbxObject importPosConstraint = importedScene.FindSrcObject(constraintName); | ||
UnityEngine.Debug.Log($"imported type is {importPosConstraint.GetType()}"); | ||
FbxConstraintPosition p = (FbxConstraintPosition)importPosConstraint; | ||
FbxConstraint pp = (FbxConstraint)importPosConstraint; // fails here | ||
} | ||
} | ||
} | ||
} | ||
// |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pulling in all the constructors, and one of them has an type we don't map -- so you get a SWIGTYPE.