示例#1
0
        public static int CalculateEndFrameFromAnimationGroupNodes(AnimationGroup animationGroup)
        {
            int endFrame = 0;

            foreach (Guid nodeGuid in animationGroup.NodeGuids)
            {
                IINode node = Tools.GetINodeByGuid(nodeGuid);
                if (node.IsAnimated && node.TMController != null)
                {
                    int lastKey = 0;
                    if (node.TMController.PositionController != null)
                    {
                        int posKeys = node.TMController.PositionController.NumKeys;
                        lastKey = Math.Max(lastKey, node.TMController.PositionController.GetKeyTime(posKeys - 1));
                    }

                    if (node.TMController.RotationController != null)
                    {
                        int rotKeys = node.TMController.RotationController.NumKeys;
                        lastKey = Math.Max(lastKey, node.TMController.RotationController.GetKeyTime(rotKeys - 1));
                    }

                    if (node.TMController.ScaleController != null)
                    {
                        int scaleKeys = node.TMController.ScaleController.NumKeys;
                        lastKey = Math.Max(lastKey, node.TMController.ScaleController.GetKeyTime(scaleKeys - 1));
                    }
                    decimal keyTime = Decimal.Ceiling(lastKey / 160);
                    endFrame = Math.Max(endFrame, Decimal.ToInt32(keyTime));
                }
            }

            return((endFrame != 0)? endFrame : animationGroup.FrameEnd);
        }
示例#2
0
        public void AutoAssignLodInAnimationGroup()
        {
            AnimationGroupList animationGroupList = new AnimationGroupList();

            animationGroupList.LoadFromData();

            var nodes = Loader.Core.RootNode.NodeTree();

            List <IINode> nodeToAdd = new List <IINode>();

            foreach (AnimationGroup anim in animationGroupList)
            {
                nodeToAdd.Clear();
                foreach (Guid guid in anim.NodeGuids)
                {
                    IINode n = Tools.GetINodeByGuid(guid);
                    if (n == null)
                    {
                        continue;
                    }
                    if (!Regex.IsMatch(n.Name, "(?i)x[0-9]_"))
                    {
                        continue;
                    }
                    string noLodName = n.Name.Substring(3);
                    foreach (IINode node in nodes)
                    {
                        if (Regex.IsMatch(node.Name, $"(?i)x[0-9]_{noLodName}$"))
                        {
                            nodeToAdd.Add(node);
                        }
                    }
                }

                foreach (IINode n in nodeToAdd)
                {
                    List <Guid> newGuids = anim.NodeGuids.ToList();
                    newGuids.Add(n.GetGuid());
                    anim.NodeGuids = newGuids;
                }
                anim.SaveToData();
            }
        }
示例#3
0
        public void LoadFromData(string propertyName, IINode dataNode)
        {
            if (!Guid.TryParse(propertyName, out serializedId))
            {
                throw new Exception("Invalid ID, can't deserialize.");
            }

            string propertiesString = string.Empty;

            if (!dataNode.GetUserPropString(propertyName, ref propertiesString))
            {
                return;
            }

            string[] properties = propertiesString.Split(s_PropertySeparator);

            if (properties.Length < 4)
            {
                throw new Exception("Invalid number of properties, can't deserialize.");
            }

            // set dirty explicitly just before we start loading, set to false when loading is done
            // if any exception is thrown, it will have a correct value
            IsDirty = true;

            name = properties[0];
            if (!int.TryParse(properties[1], out ticksStart))
            {
                throw new Exception("Failed to parse FrameStart property.");
            }
            if (!int.TryParse(properties[2], out ticksEnd))
            {
                throw new Exception("Failed to parse FrameEnd property.");
            }

            if (string.IsNullOrEmpty(properties[3]))
            {
                return;
            }

            int numNodeIDs = properties.Length - 3;

            if (nodeGuids.Capacity < numNodeIDs)
            {
                nodeGuids.Capacity = numNodeIDs;
            }
            int numFailed = 0;

            for (int i = 0; i < numNodeIDs; ++i)
            {
                Guid guid;
                if (!Guid.TryParse(properties[3 + i], out guid))
                {
                    uint id;
                    if (!uint.TryParse(properties[3 + i], out id))
                    {
                        ++numFailed;
                        continue;
                    }
                    //node is serialized in the old way ,force the reassignation of a new Guid on
                    IINode node = Loader.Core.GetINodeByHandle(id);
                    if (node != null)
                    {
                        guid = node.GetGuid();
                    }
                }
                nodeGuids.Add(guid);
            }

            AnimationGroupNodes = new List <AnimationGroupNode>();
            foreach (Guid nodeGuid in nodeGuids)
            {
                IINode node = Tools.GetINodeByGuid(nodeGuid);

                if (node != null)
                {
                    string             name       = node.Name;
                    string             parentName = node.ParentNode.Name;
                    AnimationGroupNode nodeData   = new AnimationGroupNode(nodeGuid, name, parentName);
                    AnimationGroupNodes.Add(nodeData);
                }
            }

            if (numFailed > 0)
            {
                throw new Exception(string.Format("Failed to parse {0} node ids.", numFailed));
            }

            IsDirty = false;
        }
示例#4
0
        private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene)
        {
            IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>();

            // Retrieve and parse animation group data
            AnimationGroupList animationList = AnimationGroupList.InitAnimationGroups(this);

            foreach (AnimationGroup animGroup in animationList)
            {
                RaiseMessage("Exporter.animationGroups | " + animGroup.Name, 1);

                BabylonAnimationGroup animationGroup = new BabylonAnimationGroup
                {
                    name = animGroup.Name,
                    from = animGroup.FrameStart,
                    to   = animGroup.FrameEnd,
                    targetedAnimations = new List <BabylonTargetedAnimation>()
                };

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.NodeGuids)
                {
                    IINode maxNode = Tools.GetINodeByGuid(guid);

                    // node could have been deleted, silently ignore it
                    if (maxNode == null)
                    {
                        continue;
                    }


                    // Helpers can be exported as dummies and as bones
                    string nodeId = guid.ToString();
                    string boneId = guid.ToString() + "-bone";   // the suffix "-bone" is added in babylon export format to assure the uniqueness of IDs


                    // Node
                    BabylonNode node = null;
                    babylonScene.NodeMap.TryGetValue(nodeId, out node);
                    if (node != null)
                    {
                        if (node.animations != null && node.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(node, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = nodeId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                        else if (exportNonAnimated)
                        {
                            BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                            {
                                animation = CreatePositionAnimation(animationGroup.from, animationGroup.to, node.position),
                                targetId  = node.id
                            };

                            animationGroup.targetedAnimations.Add(targetedAnimation);
                        }
                    }

                    // bone
                    BabylonBone bone  = null;
                    int         index = 0;
                    while (index < babylonScene.SkeletonsList.Count && bone == null)
                    {
                        BabylonSkeleton skel = babylonScene.SkeletonsList[index];
                        bone = skel.bones.FirstOrDefault(b => b.id == boneId);
                        index++;
                    }

                    if (bone != null)
                    {
                        if (bone.animation != null)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(bone, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = boneId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                        else if (exportNonAnimated)
                        {
                            BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                            {
                                animation = CreateMatrixAnimation(animationGroup.from, animationGroup.to, bone.matrix),
                                targetId  = bone.id
                            };

                            animationGroup.targetedAnimations.Add(targetedAnimation);
                        }
                    }
                }

                if (animationGroup.targetedAnimations.Count > 0)
                {
                    animationGroups.Add(animationGroup);
                }
            }

            return(animationGroups);
        }
示例#5
0
        public static AnimationGroupList InitAnimationGroups(ILoggingProvider logger)
        {
            AnimationGroupList animationList = new AnimationGroupList();

            animationList.LoadFromData(Loader.Core.RootNode);

            if (animationList.Count > 0)
            {
                int timelineStart = Loader.Core.AnimRange.Start / Loader.Global.TicksPerFrame;
                int timelineEnd   = Loader.Core.AnimRange.End / Loader.Global.TicksPerFrame;

                List <string> warnings = new List <string>();
                foreach (AnimationGroup animGroup in animationList)
                {
                    // ensure min <= start <= end <= max
                    warnings.Clear();
                    if (animGroup.FrameStart < timelineStart || animGroup.FrameStart > timelineEnd)
                    {
                        warnings.Add("Start frame '" + animGroup.FrameStart + "' outside of timeline range [" + timelineStart + ", " + timelineEnd + "]. Set to timeline start time '" + timelineStart + "'");
                        animGroup.FrameStart = timelineStart;
                    }
                    if (animGroup.FrameEnd < timelineStart || animGroup.FrameEnd > timelineEnd)
                    {
                        warnings.Add("End frame '" + animGroup.FrameEnd + "' outside of timeline range [" + timelineStart + ", " + timelineEnd + "]. Set to timeline end time '" + timelineEnd + "'");
                        animGroup.FrameEnd = timelineEnd;
                    }
                    if (animGroup.FrameEnd <= animGroup.FrameStart)
                    {
                        if (animGroup.FrameEnd < animGroup.FrameStart)
                        {
                            // Strict
                            warnings.Add("End frame '" + animGroup.FrameEnd + "' lower than Start frame '" + animGroup.FrameStart + "'. Start frame set to timeline start time '" + timelineStart + "'. End frame set to timeline end time '" + timelineEnd + "'.");
                        }
                        else
                        {
                            // Equal
                            warnings.Add("End frame '" + animGroup.FrameEnd + "' equal to Start frame '" + animGroup.FrameStart + "'. Single frame animation are not allowed. Start frame set to timeline start time '" + timelineStart + "'. End frame set to timeline end time '" + timelineEnd + "'.");
                        }

                        animGroup.FrameStart = timelineStart;
                        animGroup.FrameEnd   = timelineEnd;
                    }
                    foreach (Guid guid in animGroup.NodeGuids)
                    {
                        IINode node = Tools.GetINodeByGuid(guid);
                        if (node != null)
                        {
                            if (!(node.TMController.IsKeyAtTime(animGroup.TicksStart, (1 << 0)) || node.TMController.IsKeyAtTime(animGroup.TicksStart, (1 << 1)) || node.TMController.IsKeyAtTime(animGroup.TicksStart, (1 << 2))))
                            {
                                int    key = animGroup.TicksStart / 160;
                                string msg = string.Format("Node {0} has no key on min frame: {1} of animation group {2}", node.NodeName, key, animGroup.Name);
                                warnings.Add(msg);
                            }
                            if (!(node.TMController.IsKeyAtTime(animGroup.TicksEnd, (1 << 0)) || node.TMController.IsKeyAtTime(animGroup.TicksEnd, (1 << 1)) || node.TMController.IsKeyAtTime(animGroup.TicksEnd, (1 << 2))))
                            {
                                int    key = animGroup.TicksEnd / 160;
                                string msg = string.Format("Node {0} has no key on max frame: {1} of animation group {2}", node.NodeName, key, animGroup.Name);
                                warnings.Add(msg);
                            }
                        }
                    }

                    // Print animation group warnings if any
                    // Nothing printed otherwise
                    if (warnings.Count > 0)
                    {
                        logger.RaiseWarning(animGroup.Name, 1);
                        foreach (string warning in warnings)
                        {
                            logger.RaiseWarning(warning, 2);
                        }
                    }
                }
            }

            return(animationList);
        }
示例#6
0
        public void LoadFromData(string propertyName, IINode dataNode, Dictionary <string, string> rootNodePropDictionary = null)
        {
            if (!Guid.TryParse(propertyName, out serializedId))
            {
                throw new Exception("Invalid ID, can't deserialize.");
            }


            string propertiesString = string.Empty;

            if (rootNodePropDictionary == null)
            {
                if (!dataNode.GetUserPropString(propertyName, ref propertiesString))
                {
                    return;
                }
            }
            else
            {
                if (!rootNodePropDictionary.TryGetValue(propertyName, out propertiesString))
                {
                    return;
                }
            }


            int numFailed = 0;

            try // Try using the new way, if it's not working use the old way.
            {
                SerializableAnimationGroup serialAnimGroup = new SerializableAnimationGroup(propertiesString);
                serialAnimGroup.FillSerializedData(this);
            }
            catch
            {
                int indexOfguidPart = propertiesString
                                      .Select((c, i) => new { c, i })
                                      .Where(x => x.c == s_PropertySeparator)
                                      .Skip(2)
                                      .FirstOrDefault().i;
                string[] baseProperties = propertiesString.Substring(0, indexOfguidPart)?.Split(s_PropertySeparator);
                string   guidPart       = propertiesString.Substring(indexOfguidPart + 1);

                if (baseProperties.Length != 3)
                {
                    throw new Exception("Invalid number of properties, can't deserialize.");
                }

                // set dirty explicitly just before we start loading, set to false when loading is done
                // if any exception is thrown, it will have a correct value
                IsDirty = true;

                name = baseProperties[0];
                if (!int.TryParse(baseProperties[1], out ticksStart))
                {
                    throw new Exception("Failed to parse FrameStart property.");
                }
                if (!int.TryParse(baseProperties[2], out ticksEnd))
                {
                    throw new Exception("Failed to parse FrameEnd property.");
                }

                if (string.IsNullOrEmpty(guidPart) || guidPart == s_GUIDTypeSeparator.ToString())
                {
                    return;
                }


                if (!guidPart.Contains(s_GUIDTypeSeparator))
                {
                    // to grant retro-compatiblity
                    numFailed = ParseOldProperties(guidPart);
                }
                else
                {
                    //new format with nodes and node materials guid
                    numFailed = ParseNewProperties(guidPart);
                }
            }


            AnimationGroupNodes = new List <AnimationGroupNode>();
            foreach (Guid nodeGuid in nodeGuids)
            {
                IINode node = Tools.GetINodeByGuid(nodeGuid);

                if (node != null)
                {
                    string             name       = node.Name;
                    string             parentName = node.ParentNode.Name;
                    AnimationGroupNode nodeData   = new AnimationGroupNode(nodeGuid, name, parentName);
                    AnimationGroupNodes.Add(nodeData);
                }
            }

            AnimationGroupMaterials = new List <AnimationGroupMaterial>();
            foreach (Guid materialGUID in materialsGuids)
            {
                IMtl mat = Tools.GetIMtlByGuid(materialGUID);

                if (mat != null)
                {
                    string name = mat.Name;
                    AnimationGroupMaterial matData = new AnimationGroupMaterial(materialGUID, name);
                    AnimationGroupMaterials.Add(matData);
                }
            }

            if (numFailed > 0)
            {
                throw new Exception(string.Format("Failed to parse {0} node ids.", numFailed));
            }

            IsDirty = false;
        }
示例#7
0
        public void LoadFromData(string propertyName)
        {
            if (!propertyName.StartsWith(s_PropertyNamePrefix))
            {
                throw new Exception("Invalid property name, can't deserialize.");
            }


            string itemGuidStr = propertyName.Remove(0, s_PropertyNamePrefix.Length);


            if (!Guid.TryParse(itemGuidStr, out itemGuid))
            {
                Loader.Core.PushPrompt("Error: Invalid ID, can't deserialize.");
                return;
            }

            IINode iNode = Tools.GetINodeByGuid(itemGuid);

            if (iNode == null)
            {
                iNode = Loader.Core.RootNode;
            }

            // set dirty explicitly just before we start loading, set to false when loading is done
            // if any exception is thrown, it will have a correct value
            IsDirty = true;

            NodeHandle = iNode.Handle;

            string propertiesString = string.Empty;

            if (!iNode.GetUserPropString(propertyName, ref propertiesString))
            {
                return; // node has no properties yet
            }
            string[] properties = propertiesString.Split(s_PropertySeparator);
            if (properties.Length < 2)
            {
                throw new Exception("Invalid number of properties, can't deserialize.");
            }


            if (!bool.TryParse(properties[0], out selected))
            {
                throw new Exception(string.Format("Failed to parse selected property from string {0}", properties[0]));
            }


            SetExportFilePath(properties[1]);
            SetExportTexturesFolderPath(properties[2]);
            List <IILayer> layers = StringToLayers(properties[3]);

            if (layers.Count > 0)
            {
                SetExportLayers(layers);
            }



            IsDirty = false;
        }
示例#8
0
        private IList <BabylonAnimationGroup> ExportAnimationGroups(BabylonScene babylonScene)
        {
            IList <BabylonAnimationGroup> animationGroups = new List <BabylonAnimationGroup>();

            // Retrieve and parse animation group data
            AnimationGroupList animationList = AnimationGroupList.InitAnimationGroups(logger);

            foreach (AnimationGroup animGroup in animationList)
            {
                logger?.RaiseMessage("Exporter.animationGroups | " + animGroup.Name, 1);
                BabylonAnimationGroup animationGroup = new BabylonAnimationGroup
                {
                    name               = animGroup.Name,
                    from               = animGroup.FrameStart,
                    to                 = animGroup.FrameEnd,
                    keepNonAnimated    = animGroup.KeepNonAnimated,
                    targetedAnimations = new List <BabylonTargetedAnimation>()
                };

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.NodeGuids)
                {
                    IINode maxNode = Tools.GetINodeByGuid(guid);

                    // node could have been deleted, silently ignore it
                    if (maxNode == null)
                    {
                        continue;
                    }

                    if (exportParameters.exportAsSubmodel && !maxNode.Selected)
                    {
                        continue;
                    }


                    // Helpers can be exported as dummies and as bones
                    string nodeId = maxNode.GetGuid().ToString();
                    string boneId = isGltfExported?maxNode.GetGuid().ToString(): maxNode.GetGuid().ToString() + "-bone";   // the suffix "-bone" is added in babylon export format to assure the uniqueness of IDs

                    // Node
                    BabylonNode node = null;
                    babylonScene.NodeMap.TryGetValue(nodeId, out node);
                    if (node != null)
                    {
                        if (node.animations != null && node.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(node, animationGroup.from, animationGroup.to);

                            if (!animGroup.KeepStaticAnimation)
                            {
                                RemoveStaticAnimations(ref animations);
                            }

                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = nodeId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }

                    // bone
                    BabylonBone bone  = null;
                    int         index = 0;
                    while (index < babylonScene.SkeletonsList.Count && bone == null)
                    {
                        BabylonSkeleton skel = babylonScene.SkeletonsList[index];
                        bone = skel.bones.FirstOrDefault(b => b.id == boneId);
                        index++;
                    }

                    if (bone != null)
                    {
                        if (bone.animation != null)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(bone, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = boneId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }
                }

                // add animations of each nodes contained in the animGroup
                foreach (Guid guid in animGroup.MaterialGuids)
                {
                    IMtl maxMtl = Tools.GetIMtlByGuid(guid);

                    // mat could have been deleted, silently ignore it
                    if (maxMtl == null)
                    {
                        continue;
                    }

                    string matId = maxMtl.GetGuid().ToString();

                    // Material
                    BabylonMaterial material = null;
                    material = babylonScene.MaterialsList.FirstOrDefault(x => x.id == matId);
                    if (material != null)
                    {
                        if (material.animations != null && material.animations.Length != 0)
                        {
                            IList <BabylonAnimation> animations = GetSubAnimations(material, animationGroup.from, animationGroup.to);
                            foreach (BabylonAnimation animation in animations)
                            {
                                BabylonTargetedAnimation targetedAnimation = new BabylonTargetedAnimation
                                {
                                    animation = animation,
                                    targetId  = matId
                                };

                                animationGroup.targetedAnimations.Add(targetedAnimation);
                            }
                        }
                    }
                }

                if (animationGroup.targetedAnimations.Count > 0)
                {
                    animationGroups.Add(animationGroup);
                }
            }

            return(animationGroups);
        }