예제 #1
0
        private List <ICommand> SetupSingleAnimation(OperatorPart opPart, double keyframeTime)
        {
            var context = new OperatorPartContext()
            {
                Time = (float)keyframeTime
            };
            float currentValue = opPart.Eval(context).Value;

            // this command is needed to restore the original value correctly when undoing this, for doing it it's redundant
            var setValueCommand = new SetFloatValueCommand(opPart, currentValue);

            var compOp            = opPart.Parent.Parent;
            var addCurveOpCommand = new AddOperatorCommand(compOp, CurveID, 100, 100, 100, false);
            var curveOpInstanceId = addCurveOpCommand.AddedInstanceID;
            var addTimeOpCommand  = new AddOperatorCommand(compOp, CurrentTimeID, 100, 100, 100, false);

            var curveMetaOp = MetaManager.Instance.GetMetaOperator(CurveID);
            var timeMetaOp  = MetaManager.Instance.GetMetaOperator(CurrentTimeID);

            var timeToCurve = new MetaConnection(addTimeOpCommand.AddedInstanceID, timeMetaOp.Outputs[0].ID,
                                                 addCurveOpCommand.AddedInstanceID, curveMetaOp.Inputs[0].ID);
            var connectionTimeToCurveCommand = new InsertConnectionCommand(compOp.Definition, timeToCurve, 0);

            var curveToCurrent = new MetaConnection(addCurveOpCommand.AddedInstanceID, curveMetaOp.Outputs[0].ID,
                                                    opPart.Parent.ID, opPart.ID);
            var connectionCurveToCurrentCommand = new InsertConnectionCommand(compOp.Definition, curveToCurrent, 0);

            var addKeyframeCommand = new AddOrUpdateKeyframeCommand(keyframeTime, currentValue, compOp, curveOpInstanceId, curveMetaOp.Inputs[0].ID);

            return(new List <ICommand>()
            {
                setValueCommand,
                addCurveOpCommand,
                addTimeOpCommand,
                connectionTimeToCurveCommand,
                connectionCurveToCurrentCommand,
                addKeyframeCommand
            });
        }
예제 #2
0
        public AddOperatorAndConnectToInputsCommand(Operator compositionOp, MetaOperator metaOpToAdd, IEnumerable <Operator> inputOps, Point position)
        {
            _name = "Add Operator And Connect";

            var addOperatorCommand = new AddOperatorCommand(compositionOp, metaOpToAdd.ID);

            _commands.Add(addOperatorCommand);

            var    addedInstanceID = addOperatorCommand.AddedInstanceID;
            double maxY            = Double.NegativeInfinity;
            double sumX            = 0;

            var connectedOps           = new List <Operator>();
            var usedSingleInputs       = new List <MetaInput>();
            var usedMultiInputsCounter = new Dictionary <MetaInput, int>();

            // select usable input ops, the ones with at least one output - for now
            var usableInputOps = from op in inputOps where op.Outputs.Count > 0 select op;

            foreach (var inputOp in usableInputOps)
            {
                maxY  = Math.Max(maxY, inputOp.Position.Y);
                sumX += inputOp.Position.X;

                var sourceOpID     = inputOp.ID;
                var sourceOpPartID = inputOp.Outputs[0].ID;

                var inputOpType = inputOp.Definition.Outputs[0].OpPart.Type;
                Func <FunctionType, bool> isValidInputType = type => { return(inputOpType == type || type == FunctionType.Generic); };
                Func <MetaInput, bool>    isInputUsable    = input => { return(input.IsMultiInput || !usedSingleInputs.Contains(input)); };
                var matchingTargetInput = (from input in metaOpToAdd.Inputs
                                           where isValidInputType(input.OpPart.Type) && isInputUsable(input)
                                           select input).FirstOrDefault();

                if (matchingTargetInput == null)
                {
                    continue; // try next input op
                }
                var prevConnection = (from con in compositionOp.Definition.Connections
                                      where con.SourceOpPartID == sourceOpPartID && con.SourceOpID == sourceOpID
                                      select con).FirstOrDefault();

                // Split existing connections for single selected operators
                if (prevConnection != null && inputOps.Count() == 1)
                {
                    var firstOccuranceOfTargetOpID = compositionOp.Definition.Connections.FindIndex(con => (con.TargetOpID == prevConnection.TargetOpID) &&
                                                                                                    (con.TargetOpPartID == prevConnection.TargetOpPartID));
                    var idxOfPrevConnection = compositionOp.Definition.Connections.FindIndex(con => (con.SourceOpID == prevConnection.SourceOpID) &&
                                                                                             (con.SourceOpPartID == prevConnection.SourceOpPartID) &&
                                                                                             (con.TargetOpID == prevConnection.TargetOpID) &&
                                                                                             (con.TargetOpPartID == prevConnection.TargetOpPartID));
                    int multiInputIdx = idxOfPrevConnection - firstOccuranceOfTargetOpID;

                    var conNewOpToPrevTarget = new MetaConnection(addedInstanceID, metaOpToAdd.Outputs[0].ID, prevConnection.TargetOpID, prevConnection.TargetOpPartID);
                    _commands.Add(new RemoveConnectionCommand(compositionOp.Definition, prevConnection, multiInputIdx));
                    _commands.Add(new InsertConnectionCommand(compositionOp.Definition, conNewOpToPrevTarget, multiInputIdx));
                }

                // insert new connection
                var newConnection = new MetaConnection(sourceOpID, sourceOpPartID, addedInstanceID, matchingTargetInput.ID);
                int index         = 0;
                if (matchingTargetInput.IsMultiInput)
                {
                    usedMultiInputsCounter.TryGetValue(matchingTargetInput, out index);
                    usedMultiInputsCounter[matchingTargetInput] = index + 1;
                }
                else
                {
                    usedSingleInputs.Add(matchingTargetInput);
                }

                _commands.Add(new InsertConnectionCommand(compositionOp.Definition, newConnection, index));

                connectedOps.Add(inputOp);
            }

            var posX  = position.X;
            var posY  = position.Y;
            var width = 100.0;

            // Position above connected inputs operators
            if (connectedOps.Count == 0)
            {
                // find free position in center
            }
            else if (connectedOps.Count == 1)
            {
                posX = connectedOps[0].Position.X;
                posY = connectedOps[0].Position.Y - 25;
                addOperatorCommand.Width = width;
            }
            else if (connectedOps.Count > 1)
            {
                posX = sumX / inputOps.Count();
                posY = maxY - 40;
            }
            addOperatorCommand.Position = new Point(posX, posY);
        }
        public DuplicateOperatorsCommand(MetaOperator sourceCompositionOp, MetaOperator targetCompositionOp, IEnumerable <Operator> opsToDuplicate)
        {
            _name = "Duplicate Operators";

            _commands = new List <ICommand>();

            var offset = new Point(100, 100);

            var originalToCopyMap = new Dictionary <Guid, Guid>();
            var toDuplicate       = opsToDuplicate as Operator[] ?? opsToDuplicate.ToArray();

            foreach (var op in toDuplicate)
            {
                var position = new Point(op.Position.X + offset.X, op.Position.Y + offset.Y);

                // copy op
                var addOperatorCmd = new AddOperatorCommand(targetCompositionOp, op.Definition.ID, position.X, position.Y, op.Width, op.Visible);
                foreach (var state in sourceCompositionOp.Operators[op.ID].Item2.OperatorPartStates)
                {
                    addOperatorCmd.OperatorPartStates.Add(state.Key, state.Value.Clone());
                }
                originalToCopyMap[op.ID] = addOperatorCmd.AddedInstanceID;
                _commands.Add(addOperatorCmd);

                // copy op properties
                var updatePropertiesCmd = new UpdateOperatorPropertiesCommand(op.Definition.ID, addOperatorCmd.AddedInstanceID,
                                                                              new UpdateOperatorPropertiesCommand.Entry(op)
                {
                    Position = position
                });
                _commands.Add(updatePropertiesCmd);

                // copy input parameters
                foreach (var input in op.Inputs)
                {
                    if (!input.IsDefaultFuncSet)
                    {
                        // if default func is not set update the input value
                        var value = (input.Func as Utilities.ValueFunction).Value;
//                        var setInputValueCmd = new UpdateOperatorPartValueFunctionCommand(op.Definition.ID, addOperatorCmd.AddedInstanceID, input.ID,
//                                                                                          true, value);
//                        _commands.Add(setInputValueCmd);
                    }
                }
            }


            // copy connections between duplicated ops
            // first get the connections between the original ops
            var internalConnections = from con in sourceCompositionOp.Connections
                                      from sourceOp in toDuplicate
                                      from targetOp in toDuplicate
                                      where con.SourceOpID == sourceOp.ID
                                      where con.TargetOpID == targetOp.ID
                                      select con;

            // sort them as stored in parent op in order to preserve multi input order
            var allConnectionsSorted = new List <MetaConnection>(); // these are later on needed to restore multi input order!

            foreach (var con in sourceCompositionOp.Connections)
            {
                if (internalConnections.Contains(con))
                {
                    allConnectionsSorted.Add(con);
                }
            }

            // create a group for each input
            var groupedConnections = (from con in allConnectionsSorted
                                      group con by(con.TargetOpID.ToString() + con.TargetOpPartID.ToString())
                                      into g
                                      select g).ToList();

            // insert the connections to new op
            foreach (var conGroup in groupedConnections)
            {
                var index = 0;
                foreach (var con in conGroup)
                {
                    var conBetweenNewOps = new MetaConnection(originalToCopyMap[con.SourceOpID], con.SourceOpPartID,
                                                              originalToCopyMap[con.TargetOpID], con.TargetOpPartID);
                    _commands.Add(new InsertConnectionCommand(targetCompositionOp, conBetweenNewOps, index));
                    index++;
                }
            }
        }