protected override void OnUpdate()
    {
        var beginSystem = World.GetExistingSystem <ChangeDetectionSystemBegin>();

        if (beginSystem == null)
        {
            UnityEngine.Debug.LogWarning($"{nameof(ChangeDetectionSystemEnd)} cannot detect changes without the existance of {nameof(ChangeDetectionSystemBegin)}");
            return;
        }

        if (!beginSystem.HasUpdatedAtLeastOnce)
        {
            return;
        }

        ChangeDetection.RecordEntityTrace(EntityManager, _endTrace);

        // compare 'begin values' with 'end values'
        ChangeDetection.CompareAndLogChanges(beginSystem.Trace, _endTrace);
    }
示例#2
0
    /// <inheritdoc />
    public Task SetParametersAsync(ParameterView parameters)
    {
        // Implementing the parameter binding manually, instead of just calling
        // parameters.SetParameterProperties(this), is just a very slight perf optimization
        // and makes it simpler impose rules about the params being required or not.

        var hasSuppliedValue = false;
        var previousValue    = Value;
        var previousFixed    = IsFixed;

        Value        = default;
        ChildContent = null;
        Name         = null;
        IsFixed      = false;

        foreach (var parameter in parameters)
        {
            if (parameter.Name.Equals(nameof(Value), StringComparison.OrdinalIgnoreCase))
            {
                Value            = (TValue)parameter.Value;
                hasSuppliedValue = true;
            }
            else if (parameter.Name.Equals(nameof(ChildContent), StringComparison.OrdinalIgnoreCase))
            {
                ChildContent = (RenderFragment)parameter.Value;
            }
            else if (parameter.Name.Equals(nameof(Name), StringComparison.OrdinalIgnoreCase))
            {
                Name = (string)parameter.Value;
                if (string.IsNullOrEmpty(Name))
                {
                    throw new ArgumentException($"The parameter '{nameof(Name)}' for component '{nameof(CascadingValue<TValue>)}' does not allow null or empty values.");
                }
            }
            else if (parameter.Name.Equals(nameof(IsFixed), StringComparison.OrdinalIgnoreCase))
            {
                IsFixed = (bool)parameter.Value;
            }
            else
            {
                throw new ArgumentException($"The component '{nameof(CascadingValue<TValue>)}' does not accept a parameter with the name '{parameter.Name}'.");
            }
        }

        if (_hasSetParametersPreviously && IsFixed != previousFixed)
        {
            throw new InvalidOperationException($"The value of {nameof(IsFixed)} cannot be changed dynamically.");
        }

        _hasSetParametersPreviously = true;

        // It's OK for the value to be null, but some "Value" param must be supplied
        // because it serves no useful purpose to have a <CascadingValue> otherwise.
        if (!hasSuppliedValue)
        {
            throw new ArgumentException($"Missing required parameter '{nameof(Value)}' for component '{GetType().Name}'.");
        }

        // Rendering is most efficient when things are queued from rootmost to leafmost.
        // Given a components A (parent) -> B (child), you want them to be queued in order
        // [A, B] because if you had [B, A], then the render for A might change B's params
        // making it render again, so you'd render [B, A, B], which is wasteful.
        // At some point we might consider making the render queue actually enforce this
        // ordering during insertion.
        //
        // For the CascadingValue component, this observation is why it's important to render
        // ourself before notifying subscribers (which can be grandchildren or deeper).
        // If we rerendered subscribers first, then our own subsequent render might cause an
        // further update that makes those nested subscribers get rendered twice.
        _renderHandle.Render(Render);

        if (_subscribers != null && ChangeDetection.MayHaveChanged(previousValue, Value))
        {
            NotifySubscribers(parameters.Lifetime);
        }

        return(Task.CompletedTask);
    }
示例#3
0
        bool TempInputsHaveChanged(TempEntry entry, ChangeDetection detection)
        {
            for (int i = 0; i < entry.Inputs.Count; i++)
            {
                if (CheckChanged(detection, new FileInfo(entry.InputPaths[i]), entry.Inputs[i]))
                    return true;
            }

            return entry.TempDependencies.Any(t => TempInputsHaveChanged(t, detection));
        }
示例#4
0
        bool CheckChanged(ChangeDetection detection, FileInfo file, FileEntry entry)
        {
            if (!file.Exists)
                return true;

            if ((detection & ChangeDetection.Length) != 0 && file.Length != entry.Length)
                return true;

            if ((detection & ChangeDetection.Timestamp) != 0 && file.LastWriteTimeUtc != entry.Timestamp)
                return true;

            if ((detection & ChangeDetection.Hash) != 0 && HashFile(file) != entry.Hash)
                return true;

            return false;
        }
示例#5
0
 protected override void OnUpdate()
 {
     HasUpdatedAtLeastOnce = true;
     ChangeDetection.RecordEntityTrace(EntityManager, Trace);
 }