public abstract class

SplineSet

extends java.lang.Object

 java.lang.Object

↳androidx.constraintlayout.core.motion.utils.SplineSet

Subclasses:

SplineSet.CustomSet, SplineSet.CustomSpline, ViewSpline, ViewSpline.PathRotate, ViewSpline.CustomSet

Gradle dependencies

compile group: 'androidx.constraintlayout', name: 'constraintlayout-core', version: '1.1.0-beta01'

  • groupId: androidx.constraintlayout
  • artifactId: constraintlayout-core
  • version: 1.1.0-beta01

Artifact androidx.constraintlayout:constraintlayout-core:1.1.0-beta01 it located at Google repository (https://maven.google.com/)

Overview

This engine allows manipulation of attributes by Curves

Summary

Fields
protected CurveFitmCurveFit

protected int[]mTimePoints

protected float[]mValues

Constructors
publicSplineSet()

Methods
public floatget(float t)

public CurveFitgetCurveFit()

public floatgetSlope(float t)

public static SplineSetmakeCustomSpline(java.lang.String str, KeyFrameArray.CustomArray attrList)

public static SplineSetmakeCustomSplineSet(java.lang.String str, KeyFrameArray.CustomVar attrList)

public static SplineSetmakeSpline(java.lang.String str, long currentTime)

public voidsetPoint(int position, float value)

public voidsetProperty(TypedValues widget, float t)

public voidsetType(java.lang.String type)

public voidsetup(int curveType)

public java.lang.StringtoString()

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Fields

protected CurveFit mCurveFit

protected int[] mTimePoints

protected float[] mValues

Constructors

public SplineSet()

Methods

public void setProperty(TypedValues widget, float t)

public java.lang.String toString()

public void setType(java.lang.String type)

public float get(float t)

public float getSlope(float t)

public CurveFit getCurveFit()

public void setPoint(int position, float value)

public void setup(int curveType)

public static SplineSet makeCustomSpline(java.lang.String str, KeyFrameArray.CustomArray attrList)

public static SplineSet makeCustomSplineSet(java.lang.String str, KeyFrameArray.CustomVar attrList)

public static SplineSet makeSpline(java.lang.String str, long currentTime)

Source

/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.constraintlayout.core.motion.utils;

import androidx.constraintlayout.core.motion.CustomAttribute;
import androidx.constraintlayout.core.motion.CustomVariable;
import androidx.constraintlayout.core.motion.MotionWidget;
import androidx.constraintlayout.core.state.WidgetFrame;

import java.text.DecimalFormat;
import java.util.Arrays;

/**
 * This engine allows manipulation of attributes by Curves
 *
 *
 */

public abstract class SplineSet {
    private static final String TAG = "SplineSet";
    protected CurveFit mCurveFit;
    protected int[] mTimePoints = new int[10];
    protected float[] mValues = new float[10];
    private int mCount;
    private String mType;

    // @TODO: add description
    public void setProperty(TypedValues widget, float t) {
        widget.setValue(TypedValues.AttributesType.getId(mType), get(t));
    }

    @Override
    public String toString() {
        String str = mType;
        DecimalFormat df = new DecimalFormat("##.##");
        for (int i = 0; i < mCount; i++) {
            str += "[" + mTimePoints[i] + " , " + df.format(mValues[i]) + "] ";

        }
        return str;
    }

    public void setType(String type) {
        mType = type;
    }

    // @TODO: add description
    public float get(float t) {
        return (float) mCurveFit.getPos(t, 0);
    }

    // @TODO: add description
    public float getSlope(float t) {
        return (float) mCurveFit.getSlope(t, 0);
    }

    public CurveFit getCurveFit() {
        return mCurveFit;
    }

    // @TODO: add description
    public void setPoint(int position, float value) {
        if (mTimePoints.length < mCount + 1) {
            mTimePoints = Arrays.copyOf(mTimePoints, mTimePoints.length * 2);
            mValues = Arrays.copyOf(mValues, mValues.length * 2);
        }
        mTimePoints[mCount] = position;
        mValues[mCount] = value;
        mCount++;
    }

    // @TODO: add description
    public void setup(int curveType) {
        if (mCount == 0) {
            return;
        }

        Sort.doubleQuickSort(mTimePoints, mValues, 0, mCount - 1);

        int unique = 1;

        for (int i = 1; i < mCount; i++) {
            if (mTimePoints[i - 1] != mTimePoints[i]) {
                unique++;
            }
        }

        double[] time = new double[unique];
        double[][] values = new double[unique][1];
        int k = 0;
        for (int i = 0; i < mCount; i++) {
            if (i > 0 && mTimePoints[i] == mTimePoints[i - 1]) {
                continue;
            }

            time[k] = mTimePoints[i] * 1E-2;
            values[k][0] = mValues[i];
            k++;
        }
        mCurveFit = CurveFit.get(curveType, time, values);
    }

    // @TODO: add description
    public static SplineSet makeCustomSpline(String str, KeyFrameArray.CustomArray attrList) {
        return new CustomSet(str, attrList);
    }

    // @TODO: add description
    public static SplineSet makeCustomSplineSet(String str, KeyFrameArray.CustomVar attrList) {
        return new CustomSpline(str, attrList);
    }

    // @TODO: add description
    public static SplineSet makeSpline(String str, long currentTime) {

        return new CoreSpline(str, currentTime);
    }

    private static class Sort {

        static void doubleQuickSort(int[] key, float[] value, int low, int hi) {
            int[] stack = new int[key.length + 10];
            int count = 0;
            stack[count++] = hi;
            stack[count++] = low;
            while (count > 0) {
                low = stack[--count];
                hi = stack[--count];
                if (low < hi) {
                    int p = partition(key, value, low, hi);
                    stack[count++] = p - 1;
                    stack[count++] = low;
                    stack[count++] = hi;
                    stack[count++] = p + 1;
                }
            }
        }

        private static int partition(int[] array, float[] value, int low, int hi) {
            int pivot = array[hi];
            int i = low;
            for (int j = low; j < hi; j++) {
                if (array[j] <= pivot) {
                    swap(array, value, i, j);
                    i++;
                }
            }
            swap(array, value, i, hi);
            return i;
        }

        private static void swap(int[] array, float[] value, int a, int b) {
            int tmp = array[a];
            array[a] = array[b];
            array[b] = tmp;
            float tmpv = value[a];
            value[a] = value[b];
            value[b] = tmpv;
        }
    }


    public static class CustomSet extends SplineSet {
        String mAttributeName;
        KeyFrameArray.CustomArray mConstraintAttributeList;
        float[] mTempValues;

        @SuppressWarnings("StringSplitter")
        public CustomSet(String attribute, KeyFrameArray.CustomArray attrList) {
            mAttributeName = attribute.split(",")[1];
            mConstraintAttributeList = attrList;
        }

        // @TODO: add description
        @Override
        public void setup(int curveType) {
            int size = mConstraintAttributeList.size();
            int dimensionality = mConstraintAttributeList.valueAt(0).numberOfInterpolatedValues();
            double[] time = new double[size];
            mTempValues = new float[dimensionality];
            double[][] values = new double[size][dimensionality];
            for (int i = 0; i < size; i++) {

                int key = mConstraintAttributeList.keyAt(i);
                CustomAttribute ca = mConstraintAttributeList.valueAt(i);

                time[i] = key * 1E-2;
                ca.getValuesToInterpolate(mTempValues);
                for (int k = 0; k < mTempValues.length; k++) {
                    values[i][k] = mTempValues[k];
                }

            }
            mCurveFit = CurveFit.get(curveType, time, values);
        }

        // @TODO: add description
        @Override
        public void setPoint(int position, float value) {
            throw new RuntimeException("don't call for custom "
                    + "attribute call setPoint(pos, ConstraintAttribute)");
        }

        // @TODO: add description
        public void setPoint(int position, CustomAttribute value) {
            mConstraintAttributeList.append(position, value);
        }

        // @TODO: add description
        public void setProperty(WidgetFrame view, float t) {
            mCurveFit.getPos(t, mTempValues);
            view.setCustomValue(mConstraintAttributeList.valueAt(0), mTempValues);
        }
    }


    private static class CoreSpline extends SplineSet {
        String mType;
        @SuppressWarnings("unused") long mStart;

        CoreSpline(String str, long currentTime) {
            mType = str;
            mStart = currentTime;
        }

        @Override
        public void setProperty(TypedValues widget, float t) {
            int id = widget.getId(mType);
            widget.setValue(id, get(t));
        }
    }

    public static class CustomSpline extends SplineSet {
        String mAttributeName;
        KeyFrameArray.CustomVar mConstraintAttributeList;
        float[] mTempValues;

        @SuppressWarnings("StringSplitter")
        public CustomSpline(String attribute, KeyFrameArray.CustomVar attrList) {
            mAttributeName = attribute.split(",")[1];
            mConstraintAttributeList = attrList;
        }

        // @TODO: add description
        @Override
        public void setup(int curveType) {
            int size = mConstraintAttributeList.size();
            int dimensionality = mConstraintAttributeList.valueAt(0).numberOfInterpolatedValues();
            double[] time = new double[size];
            mTempValues = new float[dimensionality];
            double[][] values = new double[size][dimensionality];
            for (int i = 0; i < size; i++) {

                int key = mConstraintAttributeList.keyAt(i);
                CustomVariable ca = mConstraintAttributeList.valueAt(i);

                time[i] = key * 1E-2;
                ca.getValuesToInterpolate(mTempValues);
                for (int k = 0; k < mTempValues.length; k++) {
                    values[i][k] = mTempValues[k];
                }

            }
            mCurveFit = CurveFit.get(curveType, time, values);
        }

        // @TODO: add description
        @Override
        public void setPoint(int position, float value) {
            throw new RuntimeException("don't call for custom attribute"
                    + " call setPoint(pos, ConstraintAttribute)");
        }

        // @TODO: add description
        @Override
        public void setProperty(TypedValues widget, float t) {
            setProperty((MotionWidget) widget, t);
        }

        // @TODO: add description
        public void setPoint(int position, CustomVariable value) {
            mConstraintAttributeList.append(position, value);
        }

        // @TODO: add description
        public void setProperty(MotionWidget view, float t) {
            mCurveFit.getPos(t, mTempValues);
            mConstraintAttributeList.valueAt(0).setInterpolatedValue(view, mTempValues);
        }
    }

}