private void TransformNodeMethodsAndFields(ModelNodeDefinition node)
        {
            var nodesToRemove = new List <ModelNodeDefinition>();

            List <MethodDefinition> allMethods = node.Children.OfType <MethodDefinition>().ToList();

            foreach (MethodDefinition method in allMethods)
            {
                TransformGetterMethod(method, nodesToRemove);
            }

            foreach (MethodDefinition method in allMethods)
            {
                TransformSetterMethod(method, nodesToRemove);
            }

            // If the node has both a field and a getter method with the same
            // wrapper property, prefer to call the getter.

            List <FieldDefinition> allFields = node.Children.OfType <FieldDefinition>().ToList();

            foreach (FieldDefinition method in allFields)
            {
                TransformField(method, nodesToRemove);
            }

            foreach (ModelNodeDefinition child in nodesToRemove)
            {
                child.Parent.RemoveChild(child);
            }
        }
 private void SetNodeProperties(ModelNodeDefinition modelNode, TreeNode treeNode)
 {
     if (modelNode is NamespaceDefinition)
     {
         treeNode.ImageKey         = "folder";
         treeNode.SelectedImageKey = "folder";
     }
     else if (modelNode is ClassDefinition)
     {
         treeNode.ImageKey         = "class";
         treeNode.SelectedImageKey = "class";
     }
     else if (modelNode is MethodDefinition)
     {
         treeNode.ImageKey         = "method";
         treeNode.SelectedImageKey = "method";
     }
     else if (modelNode is TypeRefDefinition)
     {
         treeNode.ImageKey         = "typeref";
         treeNode.SelectedImageKey = "typeref";
     }
     else
     {
         treeNode.ImageIndex         = 5;
         treeNode.SelectedImageIndex = 5;
     }
 }
        public void AddNode(ModelNodeDefinition node)
        {
            if (node is NamespaceDefinition)
            {
                throw new InvalidOperationException("Namespaces cannot be header child elements");
            }

            Nodes.Add(node);
            node.Header = this;
        }
        public void TransformNode(ModelNodeDefinition node)
        {
            if (node is ClassDefinition || node is NamespaceDefinition)
            {
                TransformNodeMethodsAndFields(node);
            }

            foreach (ModelNodeDefinition child in node.Children)
            {
                TransformNode(child);
            }
        }
示例#5
0
        public static string Get(ModelNodeDefinition node)
        {
            var method = node as MethodDefinition;

            if (method != null)
            {
                var name       = method.Name;
                var parameters = string.Join(", ", method.Parameters.Select(p => p.Name));
                return($"{name}({parameters})");
            }
            return(node.Name);
        }
        public void Parse(Cursor cursor, CppParserContext context)
        {
            string fieldName = cursor.Spelling;
            var    field     = new FieldDefinition(fieldName, new TypeRefDefinition(cursor.Type));

            ModelNodeDefinition parent = context.GetContainingClassOrNamespace();

            if (parent is NamespaceDefinition)
            {
                field.Header = context.Header;
            }
            parent.AddChild(field);
        }
        private void CloneNodeWithStructure(ModelNodeDefinition node)
        {
            if (IsTopLevelNodeInNamespace(node))
            {
                var headerClone = CloneSourceItem(node.Header) as HeaderDefinition;
                headerClone.AddNode(node);
            }

            foreach (var child in node.Children)
            {
                CloneNodeWithStructure(child);
            }
        }
示例#8
0
        private IToken TokenizeNode(ModelNodeDefinition node)
        {
            if (node is ClassDefinition @class)
            {
                return(_classTokenizer.Tokenize(@class));
            }

            if (node is EnumDefinition @enum)
            {
                return(_enumTokenizer.Tokenize(@enum));
            }

            throw new NotImplementedException();
        }
        private static void Transform(ModelNodeDefinition node)
        {
            EnumDefinition @enum = node as EnumDefinition;

            if (@enum != null)
            {
                TransformEnum(@enum);
                return;
            }

            foreach (ModelNodeDefinition child in node.Children)
            {
                Transform(child);
            }
        }
示例#10
0
        private IEnumerable <ClassDefinition> EnumerateClasses(ModelNodeDefinition node)
        {
            foreach (var child in node.Children)
            {
                foreach (var childClass in EnumerateClasses(child))
                {
                    yield return(childClass);
                }
            }

            if (node is ClassDefinition @class)
            {
                yield return(@class);
            }
        }
        public static string GetFullName(this ModelNodeDefinition node)
        {
            if (!(node is ClassDefinition) || !(node is NamespaceDefinition))
            {
                throw new NotImplementedException();
            }

            ModelNodeDefinition parent = node.Parent;

            if (parent != null)
            {
                return($"{parent.GetFullName()}::{node.Name}");
            }
            return(node.Name);
        }
示例#12
0
        private static void Transform(ModelNodeDefinition node)
        {
            if (node is MethodDefinition method)
            {
                if (IsOperator(method))
                {
                    method.IsExcluded = true;
                }
                return;
            }

            foreach (ModelNodeDefinition child in node.Children)
            {
                Transform(child);
            }
        }
示例#13
0
        private static void RenameClasses(ModelNodeDefinition node)
        {
            var @class = node as ClassDefinition;

            if (@class != null && @class.Name == "UnsafeNativeMethods")
            {
                return;
            }

            if (node.Name.StartsWith("bt"))
            {
                node.Name = node.Name.Substring(2);
            }

            foreach (var child in node.Children)
            {
                RenameClasses(child);
            }
        }
        private void Order(ModelNodeDefinition node)
        {
            if (node is EnumDefinition @enum)
            {
                return;
            }

            if (node is ClassDefinition @class && @class.Name == "UnsafeNativeMethods")
            {
                return;
            }

            var newOrder = node.Children.OrderBy(n => n.Name).ToList();

            for (int i = 0; i < node.Children.Count; i++)
            {
                node.Children[i] = newOrder[i];
                Order(node.Children[i]);
            }
        }
        private void AddModelNode(ModelNodeDefinition modelNode, TreeNode parentTreeNode)
        {
            if (parentTreeNode == null)
            {
                parentTreeNode = classTree.Nodes.Add("global");
                parentTreeNode.Expand();
            }
            else
            {
                parentTreeNode = parentTreeNode.Nodes.Add(modelNode.Name);
            }
            SetNodeProperties(modelNode, parentTreeNode);

            foreach (var child in modelNode.Children
                     .OrderBy(GetNodeTypeOrder)
                     .ThenBy(c => c.Name))
            {
                AddModelNode(child, parentTreeNode);
            }
        }
        public void Parse(Cursor cursor, CppParserContext context)
        {
            string className           = cursor.Spelling;
            ModelNodeDefinition parent = context.GetContainingClassOrNamespace();

            if (HasNameConflict(className, parent))
            {
                return;
            }

            context.Class = new ClassDefinition(className);
            parent.AddChild(context.Class);
            if (parent is NamespaceDefinition)
            {
                context.Header.AddNode(context.Class);
            }

            cursor.VisitChildren(context.NodeVisitor);

            context.Class = parent as ClassDefinition;
        }
        private IList <IToken> GetClassMembers(ModelNodeDefinition node)
        {
            var members     = new List <IToken>();
            var nodesByType = node.Children.ToLookup(GetNodeType);

            foreach (var nodeType in _nodeTypeOrder)
            {
                if (_tokenizers.TryGetValue(nodeType, out INodeTokenizer tokenizer))
                {
                    foreach (var child in nodesByType[nodeType])
                    {
                        IToken childToken = tokenizer.Tokenize(child);
                        members.Add(childToken);
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            return(members);
        }
        private int GetNodeTypeOrder(ModelNodeDefinition node)
        {
            if (node is NamespaceDefinition)
            {
                return(0);
            }
            if (node is ClassDefinition)
            {
                return(1);
            }
            var method = node as MethodDefinition;

            if (method != null)
            {
                if (method.IsConstructor)
                {
                    return(2);
                }
                return(3);
            }
            return(4);
        }
 public void Merge(ModelNodeDefinition node, IList <NamespaceTreeNode> path)
 {
     if (path.Count == 1)
     {
         Nodes.Add(node);
     }
     else
     {
         NamespaceTreeNode nextSource = path[1];
         NamespaceTreeNode nextTarget = Children
                                        .FirstOrDefault(c => c.Namespace == nextSource.Namespace);
         if (nextTarget == null)
         {
             nextTarget = new NamespaceTreeNode
             {
                 Namespace = nextSource.Namespace
             };
             Children.Add(nextTarget);
         }
         nextTarget.Merge(node, path.Skip(1).ToList());
     }
 }
        public void Parse(Cursor cursor, CppParserContext context)
        {
            string methodName = cursor.Spelling;

            var parameters = new ParameterDefinition[cursor.NumArguments];

            for (uint i = 0; i < cursor.NumArguments; i++)
            {
                Cursor parameterCursor = cursor.GetArgument(i);
                parameters[i] = ParseParameter(parameterCursor, context);
            }

            context.Method = new MethodDefinition(methodName, parameters)
            {
                IsConstructor = cursor.Kind == CursorKind.Constructor,
                IsStatic      = cursor.IsStaticCxxMethod,
                IsAbstract    = IsCursorAbstract(cursor, context),
                ReturnType    = new TypeRefDefinition(cursor.ResultType)
            };

            ModelNodeDefinition parent = context.GetContainingClassOrNamespace();

            if (parent is NamespaceDefinition)
            {
                if (cursor.SemanticParent.Kind == CursorKind.ClassDecl ||
                    cursor.SemanticParent.Kind == CursorKind.ClassTemplate ||
                    cursor.SemanticParent.Kind == CursorKind.StructDecl)
                {
                    // FIXME: Clang reports a method definition as a method declaration
                    return;
                }
                context.Method.Header = context.Header;
            }
            parent.AddChild(context.Method);

            context.Method = null;
        }
 private NodeType GetNodeType(ModelNodeDefinition node)
 {
     if (node is ClassDefinition)
     {
         return(NodeType.Class);
     }
     if (node is EnumDefinition)
     {
         return(NodeType.Enum);
     }
     if (node is MethodDefinition method)
     {
         if (method.IsConstructor)
         {
             return(NodeType.Constructor);
         }
         return(NodeType.Method);
     }
     if (node is PropertyDefinition)
     {
         return(NodeType.Property);
     }
     return(NodeType.Unknown);
 }
        public IToken Tokenize(ModelNodeDefinition node)
        {
            var @enum = (EnumDefinition)node;

            var    definition = new LineToken($"public enum {@enum.Name}");
            IToken headerToken;

            if (@enum.IsFlags())
            {
                headerToken = new LinesToken(new LineToken[] {
                    new LineToken("[Flags]"),
                    definition
                }
                                             );
            }
            else
            {
                headerToken = definition;
            }

            var enumerators    = new List <IToken>();
            var lastEnumerator = @enum.Enumerators.Last();

            foreach (EnumeratorDefinition enumerator in @enum.Enumerators)
            {
                string comma          = enumerator == lastEnumerator ? "" : ",";
                string enumeratorLine = enumerator.Value != null
                    ? $"{enumerator.Name} = {enumerator.Value}{comma}"
                    : enumerator.Name + comma;
                enumerators.Add(new LineToken(enumeratorLine));
            }

            BlockToken enumToken = new BlockToken(headerToken, enumerators);

            return(enumToken);
        }
示例#23
0
        private unsafe object ExportAnimation(ICommandContext commandContext, ContentManager contentManager, bool failOnEmptyAnimation)
        {
            // Read from model file
            var modelSkeleton = LoadSkeleton(commandContext, contentManager); // we get model skeleton to compare it to real skeleton we need to map to

            AdjustSkeleton(modelSkeleton);

            TimeSpan duration;
            var      animationClips = LoadAnimation(commandContext, contentManager, out duration);

            // Fix the animation frames
            double startFrameSeconds = StartFrame.TotalSeconds;
            double endFrameSeconds   = EndFrame.TotalSeconds;
            var    startTime         = CompressedTimeSpan.FromSeconds(-startFrameSeconds);

            foreach (var clip in animationClips)
            {
                foreach (var animationCurve in clip.Value.Curves)
                {
                    animationCurve.ShiftKeys(startTime);
                }
            }

            var durationTimeSpan = TimeSpan.FromSeconds((endFrameSeconds - startFrameSeconds));

            if (duration > durationTimeSpan)
            {
                duration = durationTimeSpan;
            }

            var animationClip = new AnimationClip {
                Duration = duration
            };

            if (animationClips.Count > 0)
            {
                AnimationClip rootMotionAnimationClip = null;

                // If root motion is explicitely enabled, or if there is no skeleton, try to find root node and apply animation directly on TransformComponent
                if ((AnimationRootMotion || SkeletonUrl == null) && modelSkeleton.Nodes.Length >= 1)
                {
                    // No skeleton, map root node only
                    // TODO: For now, it seems to be located on node 1 in FBX files. Need to check if always the case, and what happens with Assimp
                    var rootNode0 = modelSkeleton.Nodes.Length >= 1 ? modelSkeleton.Nodes[0].Name : null;
                    var rootNode1 = modelSkeleton.Nodes.Length >= 2 ? modelSkeleton.Nodes[1].Name : null;
                    if ((rootNode0 != null && animationClips.TryGetValue(rootNode0, out rootMotionAnimationClip)) ||
                        (rootNode1 != null && animationClips.TryGetValue(rootNode1, out rootMotionAnimationClip)))
                    {
                        foreach (var channel in rootMotionAnimationClip.Channels)
                        {
                            var curve = rootMotionAnimationClip.Curves[channel.Value.CurveIndex];

                            // Root motion
                            var channelName = channel.Key;
                            if (channelName.StartsWith("Transform."))
                            {
                                animationClip.AddCurve($"[TransformComponent.Key]." + channelName.Replace("Transform.", string.Empty), curve);
                            }

                            // Also apply Camera curves
                            // TODO: Add some other curves?
                            if (channelName.StartsWith("Camera."))
                            {
                                animationClip.AddCurve($"[CameraComponent.Key]." + channelName.Replace("Camera.", string.Empty), curve);
                            }
                        }
                    }
                }

                // Load asset reference skeleton
                if (SkeletonUrl != null)
                {
                    var skeleton        = contentManager.Load <Skeleton>(SkeletonUrl);
                    var skeletonMapping = new SkeletonMapping(skeleton, modelSkeleton);

                    // Process missing nodes
                    foreach (var nodeAnimationClipEntry in animationClips)
                    {
                        var nodeName          = nodeAnimationClipEntry.Key;
                        var nodeAnimationClip = nodeAnimationClipEntry.Value;
                        var nodeIndex         = modelSkeleton.Nodes.IndexOf(x => x.Name == nodeName);

                        // Node doesn't exist in skeleton? skip it
                        if (nodeIndex == -1 || skeletonMapping.SourceToSource[nodeIndex] != nodeIndex)
                        {
                            continue;
                        }

                        // Skip root motion node (if any)
                        if (nodeAnimationClip == rootMotionAnimationClip)
                        {
                            continue;
                        }

                        // Find parent node
                        var parentNodeIndex = modelSkeleton.Nodes[nodeIndex].ParentIndex;

                        if (parentNodeIndex != -1 && skeletonMapping.SourceToSource[parentNodeIndex] != parentNodeIndex)
                        {
                            // Some nodes were removed, we need to concat the anim curves
                            var currentNodeIndex = nodeIndex;
                            var nodesToMerge     = new List <Tuple <ModelNodeDefinition, AnimationBlender, AnimationClipEvaluator> >();
                            while (currentNodeIndex != -1 && currentNodeIndex != skeletonMapping.SourceToSource[parentNodeIndex])
                            {
                                AnimationClip          animationClipToMerge;
                                AnimationClipEvaluator animationClipEvaluator = null;
                                AnimationBlender       animationBlender       = null;
                                if (animationClips.TryGetValue(modelSkeleton.Nodes[currentNodeIndex].Name, out animationClipToMerge))
                                {
                                    animationBlender       = new AnimationBlender();
                                    animationClipEvaluator = animationBlender.CreateEvaluator(animationClipToMerge);
                                }
                                nodesToMerge.Add(Tuple.Create(modelSkeleton.Nodes[currentNodeIndex], animationBlender, animationClipEvaluator));
                                currentNodeIndex = modelSkeleton.Nodes[currentNodeIndex].ParentIndex;
                            }

                            // Put them in proper parent to children order
                            nodesToMerge.Reverse();

                            // Find all key times
                            // TODO: We should detect discontinuities and keep them
                            var animationKeysSet = new HashSet <CompressedTimeSpan>();

                            foreach (var node in nodesToMerge)
                            {
                                if (node.Item3 != null)
                                {
                                    foreach (var curve in node.Item3.Clip.Curves)
                                    {
                                        foreach (CompressedTimeSpan time in curve.Keys)
                                        {
                                            animationKeysSet.Add(time);
                                        }
                                    }
                                }
                            }

                            // Sort key times
                            var animationKeys = animationKeysSet.ToList();
                            animationKeys.Sort();

                            var animationOperations = new FastList <AnimationOperation>();

                            var combinedAnimationClip = new AnimationClip();

                            var translationCurve = new AnimationCurve <Vector3>();
                            var rotationCurve    = new AnimationCurve <Quaternion>();
                            var scaleCurve       = new AnimationCurve <Vector3>();

                            // Evaluate at every key frame
                            foreach (var animationKey in animationKeys)
                            {
                                var matrix = Matrix.Identity;

                                // Evaluate node
                                foreach (var node in nodesToMerge)
                                {
                                    // Needs to be an array in order for it to be modified by the UpdateEngine, otherwise it would get passed by value
                                    var modelNodeDefinitions = new ModelNodeDefinition[1] {
                                        node.Item1
                                    };

                                    if (node.Item2 != null && node.Item3 != null)
                                    {
                                        // Compute
                                        AnimationClipResult animationClipResult = null;
                                        animationOperations.Clear();
                                        animationOperations.Add(AnimationOperation.NewPush(node.Item3, animationKey));
                                        node.Item2.Compute(animationOperations, ref animationClipResult);

                                        var updateMemberInfos = new List <UpdateMemberInfo>();
                                        foreach (var channel in animationClipResult.Channels)
                                        {
                                            if (channel.IsUserCustomProperty)
                                            {
                                                continue;
                                            }

                                            updateMemberInfos.Add(new UpdateMemberInfo {
                                                Name = "[0]." + channel.PropertyName, DataOffset = channel.Offset
                                            });
                                        }

                                        // TODO: Cache this
                                        var compiledUpdate = UpdateEngine.Compile(typeof(ModelNodeDefinition[]), updateMemberInfos);

                                        fixed(byte *data = animationClipResult.Data)
                                        {
                                            UpdateEngine.Run(modelNodeDefinitions, compiledUpdate, (IntPtr)data, null);
                                        }
                                    }

                                    Matrix localMatrix;
                                    var    transformTRS = modelNodeDefinitions[0].Transform;
                                    Matrix.Transformation(ref transformTRS.Scale, ref transformTRS.Rotation, ref transformTRS.Position,
                                                          out localMatrix);
                                    matrix = Matrix.Multiply(localMatrix, matrix);
                                }

                                // Done evaluating, let's decompose matrix
                                TransformTRS transform;
                                matrix.Decompose(out transform.Scale, out transform.Rotation, out transform.Position);

                                // Create a key
                                translationCurve.KeyFrames.Add(new KeyFrameData <Vector3>(animationKey, transform.Position));
                                rotationCurve.KeyFrames.Add(new KeyFrameData <Quaternion>(animationKey, transform.Rotation));
                                scaleCurve.KeyFrames.Add(new KeyFrameData <Vector3>(animationKey, transform.Scale));
                            }

                            combinedAnimationClip.AddCurve($"{nameof(ModelNodeTransformation.Transform)}.{nameof(TransformTRS.Position)}", translationCurve);
                            combinedAnimationClip.AddCurve($"{nameof(ModelNodeTransformation.Transform)}.{nameof(TransformTRS.Rotation)}", rotationCurve);
                            combinedAnimationClip.AddCurve($"{nameof(ModelNodeTransformation.Transform)}.{nameof(TransformTRS.Scale)}", scaleCurve);
                            nodeAnimationClip = combinedAnimationClip;
                        }

                        var transformStart    = $"{nameof(ModelNodeTransformation.Transform)}.";
                        var transformPosition = $"{nameof(ModelNodeTransformation.Transform)}.{nameof(TransformTRS.Position)}";

                        foreach (var channel in nodeAnimationClip.Channels)
                        {
                            var curve = nodeAnimationClip.Curves[channel.Value.CurveIndex];

                            // TODO: Root motion
                            var channelName = channel.Key;
                            if (channelName.StartsWith(transformStart))
                            {
                                if (channelName == transformPosition)
                                {
                                    // Translate node with parent 0 using PivotPosition
                                    var keyFrames = ((AnimationCurve <Vector3>)curve).KeyFrames;
                                    for (int i = 0; i < keyFrames.Count; ++i)
                                    {
                                        if (parentNodeIndex == 0)
                                        {
                                            keyFrames.Items[i].Value -= PivotPosition;
                                        }
                                        keyFrames.Items[i].Value *= ScaleImport;
                                    }
                                }
                                animationClip.AddCurve($"[ModelComponent.Key].Skeleton.NodeTransformations[{skeletonMapping.SourceToTarget[nodeIndex]}]." + channelName, curve);
                            }
                        }
                    }
                }

                if (ImportCustomAttributes)
                {
                    // Add clips clips animating other properties than node transformations
                    foreach (var nodeAnimationClipPair in animationClips)
                    {
                        var nodeName          = nodeAnimationClipPair.Key;
                        var nodeAnimationClip = nodeAnimationClipPair.Value;

                        foreach (var channel in nodeAnimationClip.Channels)
                        {
                            var channelName  = channel.Key;
                            var channelValue = channel.Value;
                            if (channelValue.IsUserCustomProperty)
                            {
                                animationClip.AddCurve(nodeName + "_" + channelName, nodeAnimationClip.Curves[channel.Value.CurveIndex], true);
                            }
                        }
                    }
                }
            }

            if (animationClip.Channels.Count == 0)
            {
                var logString = $"File {SourcePath} doesn't have any animation information.";

                if (failOnEmptyAnimation)
                {
                    commandContext.Logger.Error(logString);
                    return(null);
                }

                commandContext.Logger.Info(logString);
            }
            else
            {
                if (animationClip.Duration.Ticks == 0)
                {
                    commandContext.Logger.Verbose($"File {SourcePath} has a 0 tick long animation.");
                }

                // Optimize and set common parameters
                animationClip.RepeatMode = AnimationRepeatMode;
                animationClip.Optimize();
            }
            return(animationClip);
        }
 public IToken Tokenize(ModelNodeDefinition node)
 {
     return(Tokenize((PropertyDefinition)node));
 }
 private static bool IsTopLevelNodeInNamespace(ModelNodeDefinition node)
 {
     return(!(node is NamespaceDefinition) && node.Parent is NamespaceDefinition);
 }
 public IToken Tokenize(ModelNodeDefinition node)
 {
     return(Tokenize((ClassDefinition)node));
 }
 private static bool HasNameConflict(string className, ModelNodeDefinition parent)
 {
     return(parent.Children.Any(c => c.Name == className));
 }
示例#28
0
 public IToken Tokenize(ModelNodeDefinition node)
 {
     return(Tokenize((MethodDefinition)node));
 }