static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
{
	copy_v3_v3(out, in);
	if (!td && t->con.mode & CON_APPLY) {
		mul_m3_v3(t->con.pmtx, out);

		// With snap, a projection is alright, no need to correct for view alignment
		if (!(!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t))) {
			if (getConstraintSpaceDimension(t) == 2) {
				if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
					planeProjection(t, in, out);
				}
			}
			else if (getConstraintSpaceDimension(t) == 1) {
				float c[3];

				if (t->con.mode & CON_AXIS0) {
					copy_v3_v3(c, t->con.mtx[0]);
				}
				else if (t->con.mode & CON_AXIS1) {
					copy_v3_v3(c, t->con.mtx[1]);
				}
				else if (t->con.mode & CON_AXIS2) {
					copy_v3_v3(c, t->con.mtx[2]);
				}
				axisProjection(t, c, in, out);
			}
		}
		postConstraintChecks(t, out, pvec);
	}
}
static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
{
	copy_v3_v3(out, in);
	if (t->con.mode & CON_APPLY) {
		if (!td) {
			mul_m3_v3(t->con.pmtx, out);
			if (getConstraintSpaceDimension(t) == 2) {
				if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
					planeProjection(t, in, out);
				}
			}
			else if (getConstraintSpaceDimension(t) == 1) {
				float c[3];

				if (t->con.mode & CON_AXIS0) {
					copy_v3_v3(c, t->con.mtx[0]);
				}
				else if (t->con.mode & CON_AXIS1) {
					copy_v3_v3(c, t->con.mtx[1]);
				}
				else if (t->con.mode & CON_AXIS2) {
					copy_v3_v3(c, t->con.mtx[2]);
				}
				axisProjection(t, c, in, out);
			}
			postConstraintChecks(t, out, pvec);
			copy_v3_v3(out, pvec);
		}
		else {
			int i = 0;

			out[0] = out[1] = out[2] = 0.0f;
			if (t->con.mode & CON_AXIS0) {
				out[0] = in[i++];
			}
			if (t->con.mode & CON_AXIS1) {
				out[1] = in[i++];
			}
			if (t->con.mode & CON_AXIS2) {
				out[2] = in[i++];
			}

			mul_m3_v3(td->axismtx, out);
			if (t->flag & T_EDIT) {
				mul_m3_v3(t->obedit_mat, out);
			}
		}
	}
}
static void applyObjectConstraintVec(TransInfo *t,
                                     TransDataContainer *tc,
                                     TransData *td,
                                     const float in[3],
                                     float out[3],
                                     float pvec[3])
{
  copy_v3_v3(out, in);
  if (t->con.mode & CON_APPLY) {
    if (!td) {
      mul_m3_v3(t->con.pmtx, out);

      const int dims = getConstraintSpaceDimension(t);
      if (dims == 2) {
        if (!is_zero_v3(out)) {
          if (!isPlaneProjectionViewAligned(t)) {
            planeProjection(t, in, out);
          }
        }
      }
      else if (dims == 1) {
        float c[3];

        if (t->con.mode & CON_AXIS0) {
          copy_v3_v3(c, t->con.mtx[0]);
        }
        else if (t->con.mode & CON_AXIS1) {
          copy_v3_v3(c, t->con.mtx[1]);
        }
        else if (t->con.mode & CON_AXIS2) {
          copy_v3_v3(c, t->con.mtx[2]);
        }
        axisProjection(t, c, in, out);
      }
      postConstraintChecks(t, out, pvec);
      copy_v3_v3(out, pvec);
    }
    else {
      int i = 0;

      out[0] = out[1] = out[2] = 0.0f;
      if (t->con.mode & CON_AXIS0) {
        out[0] = in[i++];
      }
      if (t->con.mode & CON_AXIS1) {
        out[1] = in[i++];
      }
      if (t->con.mode & CON_AXIS2) {
        out[2] = in[i++];
      }

      mul_m3_v3(td->axismtx, out);
      if (t->flag & T_EDIT) {
        mul_m3_v3(tc->mat3_unit, out);
      }
    }
  }
}
void constraintNumInput(TransInfo *t, float vec[3])
{
	int mode = t->con.mode;
	if (mode & CON_APPLY) {
		float nval = (t->flag & T_NULL_ONE) ? 1.0f : 0.0f;

		if (getConstraintSpaceDimension(t) == 2) {
			int axis = mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
			if (axis == (CON_AXIS0 | CON_AXIS1)) {
				/* vec[0] = vec[0]; */ /* same */
				/* vec[1] = vec[1]; */ /* same */
				vec[2] = nval;
			}
			else if (axis == (CON_AXIS1 | CON_AXIS2)) {
				vec[2] = vec[1];
				vec[1] = vec[0];
				vec[0] = nval;
			}
			else if (axis == (CON_AXIS0 | CON_AXIS2)) {
				/* vec[0] = vec[0]; */  /* same */
				vec[2] = vec[1];
				vec[1] = nval;
			}
		}
		else if (getConstraintSpaceDimension(t) == 1) {
			if (mode & CON_AXIS0) {
				/* vec[0] = vec[0]; */ /* same */
				vec[1] = nval;
				vec[2] = nval;
			}
			else if (mode & CON_AXIS1) {
				vec[1] = vec[0];
				vec[0] = nval;
				vec[2] = nval;
			}
			else if (mode & CON_AXIS2) {
				vec[2] = vec[0];
				vec[0] = nval;
				vec[1] = nval;
			}
		}
	}
}
static void applyAxisConstraintVec(TransInfo *t,
                                   TransDataContainer *UNUSED(tc),
                                   TransData *td,
                                   const float in[3],
                                   float out[3],
                                   float pvec[3])
{
  copy_v3_v3(out, in);
  if (!td && t->con.mode & CON_APPLY) {
    mul_m3_v3(t->con.pmtx, out);

    // With snap, a projection is alright, no need to correct for view alignment
    if (!validSnap(t)) {
      const int dims = getConstraintSpaceDimension(t);
      if (dims == 2) {
        if (!is_zero_v3(out)) {
          if (!isPlaneProjectionViewAligned(t)) {
            planeProjection(t, in, out);
          }
        }
      }
      else if (dims == 1) {
        float c[3];

        if (t->con.mode & CON_AXIS0) {
          copy_v3_v3(c, t->con.mtx[0]);
        }
        else if (t->con.mode & CON_AXIS1) {
          copy_v3_v3(c, t->con.mtx[1]);
        }
        else if (t->con.mode & CON_AXIS2) {
          copy_v3_v3(c, t->con.mtx[2]);
        }
        axisProjection(t, c, in, out);
      }
    }
    postConstraintChecks(t, out, pvec);
  }
}
void startConstraint(TransInfo *t)
{
	t->con.mode |= CON_APPLY;
	*t->con.text = ' ';
	t->num.idx_max = min_ii(getConstraintSpaceDimension(t) - 1, t->idx_max);
}