983 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			983 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * This program is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU General Public License
 | 
						|
 * as published by the Free Software Foundation; either version 2
 | 
						|
 * of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software Foundation,
 | 
						|
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
						|
 *
 | 
						|
 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
 | 
						|
 * All rights reserved.
 | 
						|
 */
 | 
						|
 | 
						|
/** \file
 | 
						|
 * \ingroup edtransform
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef __TRANSFORM_H__
 | 
						|
#define __TRANSFORM_H__
 | 
						|
 | 
						|
#include "ED_numinput.h"
 | 
						|
#include "ED_transform.h"
 | 
						|
#include "ED_view3d.h"
 | 
						|
 | 
						|
#include "RE_engine.h"
 | 
						|
 | 
						|
#include "DNA_listBase.h"
 | 
						|
 | 
						|
#include "DEG_depsgraph.h"
 | 
						|
 | 
						|
/* ************************** Types ***************************** */
 | 
						|
 | 
						|
struct ARegion;
 | 
						|
struct Depsgraph;
 | 
						|
struct EditBone;
 | 
						|
struct NumInput;
 | 
						|
struct Object;
 | 
						|
struct RNG;
 | 
						|
struct ReportList;
 | 
						|
struct Scene;
 | 
						|
struct ScrArea;
 | 
						|
struct SnapObjectContext;
 | 
						|
struct TransData;
 | 
						|
struct TransDataContainer;
 | 
						|
struct TransInfo;
 | 
						|
struct TransSnap;
 | 
						|
struct TransformOrientation;
 | 
						|
struct ViewLayer;
 | 
						|
struct bConstraint;
 | 
						|
struct bContext;
 | 
						|
struct wmEvent;
 | 
						|
struct wmKeyConfig;
 | 
						|
struct wmKeyMap;
 | 
						|
struct wmTimer;
 | 
						|
 | 
						|
#include "DNA_object_enums.h"
 | 
						|
 | 
						|
/* transinfo->redraw */
 | 
						|
typedef enum {
 | 
						|
  TREDRAW_NOTHING = 0,
 | 
						|
  TREDRAW_HARD = 1,
 | 
						|
  TREDRAW_SOFT = 2,
 | 
						|
} eRedrawFlag;
 | 
						|
 | 
						|
typedef struct TransSnapPoint {
 | 
						|
  struct TransSnapPoint *next, *prev;
 | 
						|
  float co[3];
 | 
						|
} TransSnapPoint;
 | 
						|
 | 
						|
typedef struct TransSnap {
 | 
						|
  short mode;
 | 
						|
  short target;
 | 
						|
  short modePoint;
 | 
						|
  short modeSelect;
 | 
						|
  bool align;
 | 
						|
  bool project;
 | 
						|
  bool snap_self;
 | 
						|
  bool peel;
 | 
						|
  bool snap_spatial_grid;
 | 
						|
  char status;
 | 
						|
  /* Snapped Element Type (currently for objects only). */
 | 
						|
  char snapElem;
 | 
						|
  /** snapping from this point (in global-space). */
 | 
						|
  float snapPoint[3];
 | 
						|
  /** to this point (in global-space). */
 | 
						|
  float snapTarget[3];
 | 
						|
  float snapNormal[3];
 | 
						|
  char snapNodeBorder;
 | 
						|
  ListBase points;
 | 
						|
  TransSnapPoint *selectedPoint;
 | 
						|
  double last;
 | 
						|
  void (*applySnap)(struct TransInfo *, float *);
 | 
						|
  void (*calcSnap)(struct TransInfo *, float *);
 | 
						|
  void (*targetSnap)(struct TransInfo *);
 | 
						|
  /**
 | 
						|
   * Get the transform distance between two points (used by Closest snap)
 | 
						|
   *
 | 
						|
   * \note Return value can be anything,
 | 
						|
   * where the smallest absolute value defines what's closest.
 | 
						|
   */
 | 
						|
  float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
 | 
						|
 | 
						|
  /**
 | 
						|
   * Re-usable snap context data.
 | 
						|
   */
 | 
						|
  struct SnapObjectContext *object_context;
 | 
						|
} TransSnap;
 | 
						|
 | 
						|
typedef struct TransCon {
 | 
						|
  short orientation;
 | 
						|
  /** Description of the constraint for header_print. */
 | 
						|
  char text[50];
 | 
						|
  /** Matrix of the constraint space. */
 | 
						|
  float mtx[3][3];
 | 
						|
  /** Inverse matrix of the constraint space. */
 | 
						|
  float imtx[3][3];
 | 
						|
  /** Projection constraint matrix (same as #imtx with some axis == 0). */
 | 
						|
  float pmtx[3][3];
 | 
						|
  /** Initial mouse value for visual calculation
 | 
						|
   * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */
 | 
						|
  int imval[2];
 | 
						|
  /** Mode flags of the constraint. */
 | 
						|
  int mode;
 | 
						|
  void (*drawExtra)(struct TransInfo *t);
 | 
						|
 | 
						|
  /* Note: if 'tc' is NULL, 'td' must also be NULL.
 | 
						|
   * For constraints that needs to draw differently from the other
 | 
						|
   * uses this instead of the generic draw function. */
 | 
						|
 | 
						|
  /** Apply function pointer for linear vectorial transformation
 | 
						|
   * The last three parameters are pointers to the in/out/printable vectors. */
 | 
						|
  void (*applyVec)(struct TransInfo *t,
 | 
						|
                   struct TransDataContainer *tc,
 | 
						|
                   struct TransData *td,
 | 
						|
                   const float in[3],
 | 
						|
                   float out[3],
 | 
						|
                   float pvec[3]);
 | 
						|
  /** Apply function pointer for size transformation. */
 | 
						|
  void (*applySize)(struct TransInfo *t,
 | 
						|
                    struct TransDataContainer *tc,
 | 
						|
                    struct TransData *td,
 | 
						|
                    float smat[3][3]);
 | 
						|
  /** Apply function pointer for rotation transformation */
 | 
						|
  void (*applyRot)(struct TransInfo *t,
 | 
						|
                   struct TransDataContainer *tc,
 | 
						|
                   struct TransData *td,
 | 
						|
                   float vec[3],
 | 
						|
                   float *angle);
 | 
						|
} TransCon;
 | 
						|
 | 
						|
typedef struct TransDataExtension {
 | 
						|
  /** Initial object drot. */
 | 
						|
  float drot[3];
 | 
						|
  // /* Initial object drotAngle,    TODO: not yet implemented */
 | 
						|
  // float drotAngle;
 | 
						|
  // /* Initial object drotAxis, TODO: not yet implemented */
 | 
						|
  // float drotAxis[3];
 | 
						|
  /** Initial object delta quat. */
 | 
						|
  float dquat[4];
 | 
						|
  /** Initial object delta scale. */
 | 
						|
  float dscale[3];
 | 
						|
  /** Rotation of the data to transform. */
 | 
						|
  float *rot;
 | 
						|
  /** Initial rotation. */
 | 
						|
  float irot[3];
 | 
						|
  /** Rotation quaternion of the data to transform. */
 | 
						|
  float *quat;
 | 
						|
  /** Initial rotation quaternion. */
 | 
						|
  float iquat[4];
 | 
						|
  /** Rotation angle of the data to transform. */
 | 
						|
  float *rotAngle;
 | 
						|
  /** Initial rotation angle. */
 | 
						|
  float irotAngle;
 | 
						|
  /** Rotation axis of the data to transform. */
 | 
						|
  float *rotAxis;
 | 
						|
  /** Initial rotation axis. */
 | 
						|
  float irotAxis[4];
 | 
						|
  /** Size of the data to transform. */
 | 
						|
  float *size;
 | 
						|
  /** Initial size. */
 | 
						|
  float isize[3];
 | 
						|
  /** Object matrix. */
 | 
						|
  float obmat[4][4];
 | 
						|
  /** Use instead of #TransData.smtx,
 | 
						|
   * It is the same but without the #Bone.bone_mat, see #TD_PBONE_LOCAL_MTX_C. */
 | 
						|
  float l_smtx[3][3];
 | 
						|
  /** The rotscale matrix of pose bone, to allow using snap-align in translation mode,
 | 
						|
   * when td->mtx is the loc pose bone matrix (and hence can't be used to apply
 | 
						|
   * rotation in some cases, namely when a bone is in "NoLocal" or "Hinge" mode)... */
 | 
						|
  float r_mtx[3][3];
 | 
						|
  /** Inverse of previous one. */
 | 
						|
  float r_smtx[3][3];
 | 
						|
  /** Rotation mode, as defined in #eRotationModes (DNA_action_types.h). */
 | 
						|
  int rotOrder;
 | 
						|
  /** Original object transformation used for rigid bodies. */
 | 
						|
  float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle;
 | 
						|
} TransDataExtension;
 | 
						|
 | 
						|
typedef struct TransData2D {
 | 
						|
  /** Location of data used to transform (x,y,0). */
 | 
						|
  float loc[3];
 | 
						|
  /** Pointer to real 2d location of data. */
 | 
						|
  float *loc2d;
 | 
						|
 | 
						|
  /** Pointer to handle locations, if handles aren't being moved independently. */
 | 
						|
  float *h1, *h2;
 | 
						|
  float ih1[2], ih2[2];
 | 
						|
} TransData2D;
 | 
						|
 | 
						|
/**
 | 
						|
 * Used to store 2 handles for each #TransData in case the other handle wasn't selected.
 | 
						|
 * Also to unset temporary flags.
 | 
						|
 */
 | 
						|
typedef struct TransDataCurveHandleFlags {
 | 
						|
  char ih1, ih2;
 | 
						|
  char *h1, *h2;
 | 
						|
} TransDataCurveHandleFlags;
 | 
						|
 | 
						|
/** Used for sequencer transform. */
 | 
						|
typedef struct TransDataSeq {
 | 
						|
  struct Sequence *seq;
 | 
						|
  /** A copy of #Sequence.flag that may be modified for nested strips. */
 | 
						|
  int flag;
 | 
						|
  /** Use this so we can have transform data at the strips start,
 | 
						|
   * but apply correctly to the start frame. */
 | 
						|
  int start_offset;
 | 
						|
  /** one of #SELECT, #SEQ_LEFTSEL and #SEQ_RIGHTSEL. */
 | 
						|
  short sel_flag;
 | 
						|
 | 
						|
} TransDataSeq;
 | 
						|
 | 
						|
/**
 | 
						|
 * Sequencer transform customdata (stored in #TransCustomDataContainer).
 | 
						|
 */
 | 
						|
typedef struct TransSeq {
 | 
						|
  TransDataSeq *tdseq;
 | 
						|
  int min;
 | 
						|
  int max;
 | 
						|
  bool snap_left;
 | 
						|
} TransSeq;
 | 
						|
 | 
						|
/** Used for NLA transform (stored in #TransData.extra pointer). */
 | 
						|
typedef struct TransDataNla {
 | 
						|
  /** ID-block NLA-data is attached to. */
 | 
						|
  ID *id;
 | 
						|
 | 
						|
  /** Original NLA-Track that the strip belongs to. */
 | 
						|
  struct NlaTrack *oldTrack;
 | 
						|
  /** Current NLA-Track that the strip belongs to. */
 | 
						|
  struct NlaTrack *nlt;
 | 
						|
 | 
						|
  /** NLA-strip this data represents. */
 | 
						|
  struct NlaStrip *strip;
 | 
						|
 | 
						|
  /* dummy values for transform to write in - must have 3 elements... */
 | 
						|
  /** start handle. */
 | 
						|
  float h1[3];
 | 
						|
  /** end handle. */
 | 
						|
  float h2[3];
 | 
						|
 | 
						|
  /** index of track that strip is currently in. */
 | 
						|
  int trackIndex;
 | 
						|
  /** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
 | 
						|
  int handle;
 | 
						|
} TransDataNla;
 | 
						|
 | 
						|
typedef struct TransData {
 | 
						|
  /** Distance needed to affect element (for Proportionnal Editing). */
 | 
						|
  float dist;
 | 
						|
  /** Distance to the nearest element (for Proportionnal Editing). */
 | 
						|
  float rdist;
 | 
						|
  /** Factor of the transformation (for Proportionnal Editing). */
 | 
						|
  float factor;
 | 
						|
  /** Location of the data to transform. */
 | 
						|
  float *loc;
 | 
						|
  /** Initial location. */
 | 
						|
  float iloc[3];
 | 
						|
  /** Value pointer for special transforms. */
 | 
						|
  float *val;
 | 
						|
  /** Old value. */
 | 
						|
  float ival;
 | 
						|
  /** Individual data center. */
 | 
						|
  float center[3];
 | 
						|
  /** Transformation matrix from data space to global space. */
 | 
						|
  float mtx[3][3];
 | 
						|
  /** Transformation matrix from global space to data space. */
 | 
						|
  float smtx[3][3];
 | 
						|
  /** Axis orientation matrix of the data. */
 | 
						|
  float axismtx[3][3];
 | 
						|
  struct Object *ob;
 | 
						|
  /** For objects/bones, the first constraint in its constraint stack. */
 | 
						|
  struct bConstraint *con;
 | 
						|
  /** For objects, poses. 1 single malloc per TransInfo! */
 | 
						|
  TransDataExtension *ext;
 | 
						|
  /** for curves, stores handle flags for modification/cancel. */
 | 
						|
  TransDataCurveHandleFlags *hdata;
 | 
						|
  /**
 | 
						|
   * Extra data (mirrored element pointer, in editmode mesh to BMVert)
 | 
						|
   * (editbone for roll fixing) (...).
 | 
						|
   */
 | 
						|
  void *extra;
 | 
						|
  /** Various flags. */
 | 
						|
  int flag;
 | 
						|
  /** If set, copy of Object or PoseChannel protection. */
 | 
						|
  short protectflag;
 | 
						|
} TransData;
 | 
						|
 | 
						|
typedef struct TransDataMirror {
 | 
						|
  /** location of mirrored reference data. */
 | 
						|
  const float *loc_src;
 | 
						|
  /** Location of the data to transform. */
 | 
						|
  float *loc_dst;
 | 
						|
  void *extra;
 | 
						|
  /* `sign` can be -2, -1, 0 or 1. */
 | 
						|
  int sign_x : 2;
 | 
						|
  int sign_y : 2;
 | 
						|
  int sign_z : 2;
 | 
						|
} TransDataMirror;
 | 
						|
 | 
						|
typedef struct MouseInput {
 | 
						|
  void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
 | 
						|
  void (*post)(struct TransInfo *t, float values[3]);
 | 
						|
 | 
						|
  /** Initial mouse position. */
 | 
						|
  int imval[2];
 | 
						|
  bool precision;
 | 
						|
  float precision_factor;
 | 
						|
  float center[2];
 | 
						|
  float factor;
 | 
						|
  /** Additional data, if needed by the particular function. */
 | 
						|
  void *data;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Use virtual cursor, which takes precision into account
 | 
						|
   * keeping track of the cursors 'virtual' location,
 | 
						|
   * to avoid jumping values when its toggled.
 | 
						|
   *
 | 
						|
   * This works well for scaling drag motion,
 | 
						|
   * but not for rotating around a point (rotaton needs its own custom accumulator)
 | 
						|
   */
 | 
						|
  bool use_virtual_mval;
 | 
						|
  struct {
 | 
						|
    double prev[2];
 | 
						|
    double accum[2];
 | 
						|
  } virtual_mval;
 | 
						|
} MouseInput;
 | 
						|
 | 
						|
typedef struct TransCustomData {
 | 
						|
  void *data;
 | 
						|
  void (*free_cb)(struct TransInfo *,
 | 
						|
                  struct TransDataContainer *tc,
 | 
						|
                  struct TransCustomData *custom_data);
 | 
						|
  unsigned int use_free : 1;
 | 
						|
} TransCustomData;
 | 
						|
 | 
						|
typedef struct TransCenterData {
 | 
						|
  float global[3];
 | 
						|
  unsigned int is_set : 1;
 | 
						|
} TransCenterData;
 | 
						|
 | 
						|
/**
 | 
						|
 * Rule of thumb for choosing between mode/type:
 | 
						|
 * - If transform mode uses the data, assign to `mode`
 | 
						|
 *   (typically in transform.c).
 | 
						|
 * - If conversion uses the data as an extension to the #TransData, assign to `type`
 | 
						|
 *   (typically in transform_conversion.c).
 | 
						|
 */
 | 
						|
typedef struct TransCustomDataContainer {
 | 
						|
  /** Owned by the mode (grab, scale, bend... ).*/
 | 
						|
  union {
 | 
						|
    TransCustomData mode, first_elem;
 | 
						|
  };
 | 
						|
  TransCustomData type;
 | 
						|
} TransCustomDataContainer;
 | 
						|
#define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(TransCustomDataContainer) / sizeof(TransCustomData))
 | 
						|
 | 
						|
typedef struct TransDataContainer {
 | 
						|
  /**
 | 
						|
   * Use for cases we care about the active, eg: active vert of active mesh.
 | 
						|
   * if set this will _always_ be the first item in the array.
 | 
						|
   */
 | 
						|
  bool is_active;
 | 
						|
 | 
						|
  /** Transformed data (array). */
 | 
						|
  TransData *data;
 | 
						|
  /** Total number of transformed data. */
 | 
						|
  int data_len;
 | 
						|
 | 
						|
  /** Transformed data extension (array). */
 | 
						|
  TransDataExtension *data_ext;
 | 
						|
  /** Transformed data for 2d (array). */
 | 
						|
  TransData2D *data_2d;
 | 
						|
 | 
						|
  struct Object *obedit;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Store matrix, this avoids having to have duplicate check all over
 | 
						|
   * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
 | 
						|
   */
 | 
						|
  bool use_local_mat;
 | 
						|
  float mat[4][4];
 | 
						|
  float imat[4][4];
 | 
						|
  /** 3x3 copies of matrices above. */
 | 
						|
  float mat3[3][3];
 | 
						|
  float imat3[3][3];
 | 
						|
 | 
						|
  /** Normalized 'mat3' */
 | 
						|
  float mat3_unit[3][3];
 | 
						|
 | 
						|
  /** if 't->flag & T_POSE', this denotes pose object */
 | 
						|
  struct Object *poseobj;
 | 
						|
 | 
						|
  /** Center of transformation (in local-space), Calculated from #TransInfo.center_global. */
 | 
						|
  float center_local[3];
 | 
						|
 | 
						|
  /**
 | 
						|
   * Mirror option
 | 
						|
   */
 | 
						|
  struct {
 | 
						|
    union {
 | 
						|
      struct {
 | 
						|
        uint axis_x : 1;
 | 
						|
        uint axis_y : 1;
 | 
						|
        uint axis_z : 1;
 | 
						|
      };
 | 
						|
      /* For easy checking. */
 | 
						|
      char use_mirror_any;
 | 
						|
    };
 | 
						|
    /** Mirror data array. */
 | 
						|
    TransDataMirror *data;
 | 
						|
    int data_len;
 | 
						|
  } mirror;
 | 
						|
 | 
						|
  TransCustomDataContainer custom;
 | 
						|
} TransDataContainer;
 | 
						|
 | 
						|
typedef struct TransInfo {
 | 
						|
  TransDataContainer *data_container;
 | 
						|
  int data_container_len;
 | 
						|
  /** Combine length of all #TransDataContainer.data_len
 | 
						|
   * Use to check if nothing is selected or if we have a single selection. */
 | 
						|
  int data_len_all;
 | 
						|
 | 
						|
  /** Current mode. */
 | 
						|
  int mode;
 | 
						|
  /** Generic flags for special behaviors. */
 | 
						|
  int flag;
 | 
						|
  /** Special modifiers, by function, not key. */
 | 
						|
  int modifiers;
 | 
						|
  /** Current state (running, canceled. */
 | 
						|
  short state;
 | 
						|
  /** Current context/options for transform. */
 | 
						|
  int options;
 | 
						|
  /** Init value for some transformations (and rotation angle). */
 | 
						|
  float val;
 | 
						|
  void (*transform)(struct TransInfo *, const int[2]);
 | 
						|
  /** Transform function pointer. */
 | 
						|
  eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
 | 
						|
  /* event handler function pointer  RETURN 1 if redraw is needed */
 | 
						|
  /** transformed constraint. */
 | 
						|
  TransCon con;
 | 
						|
  TransSnap tsnap;
 | 
						|
  /** numerical input. */
 | 
						|
  NumInput num;
 | 
						|
  /** mouse input. */
 | 
						|
  MouseInput mouse;
 | 
						|
  /** redraw flag. */
 | 
						|
  eRedrawFlag redraw;
 | 
						|
  /** proportional circle radius. */
 | 
						|
  float prop_size;
 | 
						|
  /** proportional falloff text. */
 | 
						|
  char proptext[20];
 | 
						|
  /**
 | 
						|
   * Spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
 | 
						|
   * use for conversion and snapping.
 | 
						|
   */
 | 
						|
  float aspect[3];
 | 
						|
  /** center of transformation (in global-space) */
 | 
						|
  float center_global[3];
 | 
						|
  /** center in screen coordinates. */
 | 
						|
  float center2d[2];
 | 
						|
  /* Lazy initialize center data for when we need other center values.
 | 
						|
   * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
 | 
						|
  TransCenterData center_cache[5];
 | 
						|
  /** maximum index on the input vector. */
 | 
						|
  short idx_max;
 | 
						|
  /** Snapping Gears. */
 | 
						|
  float snap[3];
 | 
						|
  /** Spatial snapping gears(even when rotating, scaling... etc). */
 | 
						|
  float snap_spatial[3];
 | 
						|
  /** Mouse side of the cfra, 'L', 'R' or 'B' */
 | 
						|
  char frame_side;
 | 
						|
 | 
						|
  /** copy from G.vd, prevents feedback. */
 | 
						|
  float viewmat[4][4];
 | 
						|
  /** and to make sure we don't have to. */
 | 
						|
  float viewinv[4][4];
 | 
						|
  /** access G.vd from other space types. */
 | 
						|
  float persmat[4][4];
 | 
						|
  float persinv[4][4];
 | 
						|
  short persp;
 | 
						|
  short around;
 | 
						|
  /** spacetype where transforming is. */
 | 
						|
  char spacetype;
 | 
						|
  /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */
 | 
						|
  char helpline;
 | 
						|
  /** Avoid looking inside TransDataContainer obedit. */
 | 
						|
  short obedit_type;
 | 
						|
 | 
						|
  /** translation, to show for widget. */
 | 
						|
  float vec[3];
 | 
						|
  /** rot/rescale, to show for widget. */
 | 
						|
  float mat[3][3];
 | 
						|
 | 
						|
  /** orientation matrix of the current space. */
 | 
						|
  float spacemtx[3][3];
 | 
						|
  /** name of the current space, MAX_NAME. */
 | 
						|
  char spacename[64];
 | 
						|
 | 
						|
  /*************** NEW STUFF *********************/
 | 
						|
  /** event type used to launch transform. */
 | 
						|
  short launch_event;
 | 
						|
  /** Is the actual launch event a tweak event? (launch_event above is set to the corresponding
 | 
						|
   * mouse button then.) */
 | 
						|
  bool is_launch_event_tweak;
 | 
						|
 | 
						|
  struct {
 | 
						|
    /** Orientation type when when we're not constrained.
 | 
						|
     * nearly always global except for rotate which defaults to screen-space orientation. */
 | 
						|
    short unset;
 | 
						|
    /** Orientation to use when a key is pressed. */
 | 
						|
    short user;
 | 
						|
    /* Used when user is global. */
 | 
						|
    short user_alt;
 | 
						|
    short index;
 | 
						|
    short *types[2];
 | 
						|
    /* this gets used when custom_orientation is V3D_ORIENT_CUSTOM */
 | 
						|
    struct TransformOrientation *custom;
 | 
						|
  } orientation;
 | 
						|
  /** backup from view3d, to restore on end. */
 | 
						|
  short gizmo_flag;
 | 
						|
 | 
						|
  short prop_mode;
 | 
						|
 | 
						|
  /** Value taken as input, either through mouse coordinates or entered as a parameter. */
 | 
						|
  float values[4];
 | 
						|
 | 
						|
  /** Offset applied ontop of modal input. */
 | 
						|
  float values_modal_offset[4];
 | 
						|
 | 
						|
  /** Final value of the transformation (displayed in the redo panel).
 | 
						|
   * If the operator is executed directly (not modal), this value is usually the
 | 
						|
   * value of the input parameter, except when a constrain is entered. */
 | 
						|
  float values_final[4];
 | 
						|
 | 
						|
  /* Axis members for modes that use an axis separate from the orientation (rotate & shear). */
 | 
						|
 | 
						|
  /** Primary axis, rotate only uses this. */
 | 
						|
  int orient_axis;
 | 
						|
  /** Secondary axis, shear uses this. */
 | 
						|
  int orient_axis_ortho;
 | 
						|
 | 
						|
  /** Often this matrix has similar usage to #TransInfo.spacemtx however this
 | 
						|
   * is used to define extra axes to operate on, not necessarily a space.
 | 
						|
   *
 | 
						|
   * For example, by default rotation operates on the view (`orient_matrix[2]`),
 | 
						|
   * even when the current space isn't set to the view. */
 | 
						|
  float orient_matrix[3][3];
 | 
						|
  /** Don't overwrite when set by operator redo defines the orientation axis. */
 | 
						|
  bool orient_matrix_is_set;
 | 
						|
 | 
						|
  /** remove elements if operator is canceled. */
 | 
						|
  bool remove_on_cancel;
 | 
						|
 | 
						|
  void *view;
 | 
						|
  /** Only valid (non null) during an operator called function. */
 | 
						|
  struct bContext *context;
 | 
						|
  struct wmMsgBus *mbus;
 | 
						|
  struct ScrArea *area;
 | 
						|
  struct ARegion *region;
 | 
						|
  struct Depsgraph *depsgraph;
 | 
						|
  struct Scene *scene;
 | 
						|
  struct ViewLayer *view_layer;
 | 
						|
  struct ToolSettings *settings;
 | 
						|
  struct wmTimer *animtimer;
 | 
						|
  /** so we can do lookups for header text. */
 | 
						|
  struct wmKeyMap *keymap;
 | 
						|
  /** assign from the operator, or can be NULL. */
 | 
						|
  struct ReportList *reports;
 | 
						|
  /** current mouse position. */
 | 
						|
  int mval[2];
 | 
						|
  /** use for 3d view. */
 | 
						|
  float zfac;
 | 
						|
  void *draw_handle_apply;
 | 
						|
  void *draw_handle_view;
 | 
						|
  void *draw_handle_pixel;
 | 
						|
  void *draw_handle_cursor;
 | 
						|
 | 
						|
  /** Currently only used for random curve of proportional editing. */
 | 
						|
  struct RNG *rng;
 | 
						|
 | 
						|
  /** Typically for mode settings. */
 | 
						|
  TransCustomDataContainer custom;
 | 
						|
} TransInfo;
 | 
						|
 | 
						|
/* ******************** Macros & Prototypes *********************** */
 | 
						|
 | 
						|
/* transinfo->state */
 | 
						|
enum {
 | 
						|
  TRANS_STARTING = 0,
 | 
						|
  TRANS_RUNNING = 1,
 | 
						|
  TRANS_CONFIRM = 2,
 | 
						|
  TRANS_CANCEL = 3,
 | 
						|
};
 | 
						|
 | 
						|
/* transinfo->flag */
 | 
						|
enum {
 | 
						|
  T_OBJECT = 1 << 0,
 | 
						|
  /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */
 | 
						|
  T_EDIT = 1 << 1,
 | 
						|
  T_POSE = 1 << 2,
 | 
						|
  T_TEXTURE = 1 << 3,
 | 
						|
  /** Transforming the 3d view. */
 | 
						|
  T_CAMERA = 1 << 4,
 | 
						|
  /** Transforming the 3D cursor. */
 | 
						|
  T_CURSOR = 1 << 5,
 | 
						|
  /** Transform points, having no rotation/scale. */
 | 
						|
  T_POINTS = 1 << 6,
 | 
						|
 | 
						|
  /* empty slot - (1 << 7) */
 | 
						|
 | 
						|
  /** restrictions flags */
 | 
						|
  T_NO_CONSTRAINT = 1 << 8,
 | 
						|
  T_NULL_ONE = 1 << 9,
 | 
						|
  T_NO_ZERO = 1 << 10,
 | 
						|
  T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
 | 
						|
 | 
						|
  T_PROP_EDIT = 1 << 11,
 | 
						|
  T_PROP_CONNECTED = 1 << 12,
 | 
						|
  T_PROP_PROJECTED = 1 << 13,
 | 
						|
  T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
 | 
						|
 | 
						|
  T_V3D_ALIGN = 1 << 14,
 | 
						|
  /** For 2d views like uv or fcurve. */
 | 
						|
  T_2D_EDIT = 1 << 15,
 | 
						|
  T_CLIP_UV = 1 << 16,
 | 
						|
 | 
						|
  /** Auto-ik is on. */
 | 
						|
  T_AUTOIK = 1 << 18,
 | 
						|
 | 
						|
  /** Don't use mirror even if the data-block option is set. */
 | 
						|
  T_NO_MIRROR = 1 << 19,
 | 
						|
 | 
						|
  /** To indicate that the value set in the `value` parameter is the final
 | 
						|
   * value of the transformation, modified only by the constrain. */
 | 
						|
  T_INPUT_IS_VALUES_FINAL = 1 << 20,
 | 
						|
 | 
						|
  /** To specify if we save back settings at the end. */
 | 
						|
  T_MODAL = 1 << 21,
 | 
						|
 | 
						|
  /** No retopo. */
 | 
						|
  T_NO_PROJECT = 1 << 22,
 | 
						|
 | 
						|
  T_RELEASE_CONFIRM = 1 << 23,
 | 
						|
 | 
						|
  /** Alternative transformation. used to add offset to tracking markers. */
 | 
						|
  T_ALT_TRANSFORM = 1 << 24,
 | 
						|
 | 
						|
  /** #TransInfo.center has been set, don't change it. */
 | 
						|
  T_OVERRIDE_CENTER = 1 << 25,
 | 
						|
 | 
						|
  T_MODAL_CURSOR_SET = 1 << 26,
 | 
						|
 | 
						|
  T_CLNOR_REBUILD = 1 << 27,
 | 
						|
};
 | 
						|
 | 
						|
/** #TransInfo.modifiers */
 | 
						|
enum {
 | 
						|
  MOD_CONSTRAINT_SELECT = 1 << 0,
 | 
						|
  MOD_PRECISION = 1 << 1,
 | 
						|
  MOD_SNAP = 1 << 2,
 | 
						|
  MOD_SNAP_INVERT = 1 << 3,
 | 
						|
  MOD_CONSTRAINT_PLANE = 1 << 4,
 | 
						|
};
 | 
						|
 | 
						|
/* use node center for transform instead of upper-left corner.
 | 
						|
 * disabled since it makes absolute snapping not work so nicely
 | 
						|
 */
 | 
						|
// #define USE_NODE_CENTER
 | 
						|
 | 
						|
/* ******************************************************************************** */
 | 
						|
 | 
						|
/** #TransInfo.helpline */
 | 
						|
enum {
 | 
						|
  HLP_NONE = 0,
 | 
						|
  HLP_SPRING = 1,
 | 
						|
  HLP_ANGLE = 2,
 | 
						|
  HLP_HARROW = 3,
 | 
						|
  HLP_VARROW = 4,
 | 
						|
  HLP_CARROW = 5,
 | 
						|
  HLP_TRACKBALL = 6,
 | 
						|
};
 | 
						|
 | 
						|
/** #TransCon.mode, #TransInfo.con.mode */
 | 
						|
enum {
 | 
						|
  /** When set constraints are in use. */
 | 
						|
  CON_APPLY = 1 << 0,
 | 
						|
  /** These are only used for modal execution. */
 | 
						|
  CON_AXIS0 = 1 << 1,
 | 
						|
  CON_AXIS1 = 1 << 2,
 | 
						|
  CON_AXIS2 = 1 << 3,
 | 
						|
  CON_SELECT = 1 << 4,
 | 
						|
  /** Does not reorient vector to face viewport when on. */
 | 
						|
  CON_NOFLIP = 1 << 5,
 | 
						|
  CON_USER = 1 << 6,
 | 
						|
};
 | 
						|
 | 
						|
/** #TransData.flag */
 | 
						|
enum {
 | 
						|
  TD_SELECTED = 1 << 0,
 | 
						|
  TD_NOACTION = 1 << 2,
 | 
						|
  TD_USEQUAT = 1 << 3,
 | 
						|
  TD_NOTCONNECTED = 1 << 4,
 | 
						|
  /** Used for scaling of #MetaElem.rad */
 | 
						|
  TD_SINGLESIZE = 1 << 5,
 | 
						|
  /** Scale relative to individual element center */
 | 
						|
  TD_INDIVIDUAL_SCALE = 1 << 8,
 | 
						|
  TD_NOCENTER = 1 << 9,
 | 
						|
  /** #TransData.ext abused for particle key timing. */
 | 
						|
  TD_NO_EXT = 1 << 10,
 | 
						|
  /** don't transform this data */
 | 
						|
  TD_SKIP = 1 << 11,
 | 
						|
  /** if this is a bez triple, we need to restore the handles,
 | 
						|
   * if this is set #TransData.hdata needs freeing */
 | 
						|
  TD_BEZTRIPLE = 1 << 12,
 | 
						|
  /** when this is set, don't apply translation changes to this element */
 | 
						|
  TD_NO_LOC = 1 << 13,
 | 
						|
  /** For Graph Editor autosnap, indicates that point should not undergo autosnapping */
 | 
						|
  TD_NOTIMESNAP = 1 << 14,
 | 
						|
  /** For Graph Editor - curves that can only have int-values
 | 
						|
   * need their keyframes tagged with this. */
 | 
						|
  TD_INTVALUES = 1 << 15,
 | 
						|
  /** For editmode mirror, clamp axis to 0 */
 | 
						|
  TD_MIRROR_EDGE_X = 1 << 16,
 | 
						|
  TD_MIRROR_EDGE_Y = 1 << 17,
 | 
						|
  TD_MIRROR_EDGE_Z = 1 << 18,
 | 
						|
  /** For fcurve handles, move them along with their keyframes */
 | 
						|
  TD_MOVEHANDLE1 = 1 << 19,
 | 
						|
  TD_MOVEHANDLE2 = 1 << 20,
 | 
						|
  /** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
 | 
						|
   * option enabled and rotating also transforms it. */
 | 
						|
  TD_PBONE_LOCAL_MTX_P = 1 << 21,
 | 
						|
  /** Same as above but for a child bone. */
 | 
						|
  TD_PBONE_LOCAL_MTX_C = 1 << 22,
 | 
						|
};
 | 
						|
 | 
						|
/** #TransSnap.status */
 | 
						|
enum {
 | 
						|
  SNAP_FORCED = 1 << 0,
 | 
						|
  TARGET_INIT = 1 << 1,
 | 
						|
  POINT_INIT = 1 << 2,
 | 
						|
  MULTI_POINTS = 1 << 3,
 | 
						|
};
 | 
						|
 | 
						|
/** keymap modal items */
 | 
						|
/* NOTE: these values are saved in keymap files, do not change then but just add new ones. */
 | 
						|
enum {
 | 
						|
  TFM_MODAL_CANCEL = 1,
 | 
						|
  TFM_MODAL_CONFIRM = 2,
 | 
						|
  TFM_MODAL_TRANSLATE = 3,
 | 
						|
  TFM_MODAL_ROTATE = 4,
 | 
						|
  TFM_MODAL_RESIZE = 5,
 | 
						|
  TFM_MODAL_SNAP_INV_ON = 6,
 | 
						|
  TFM_MODAL_SNAP_INV_OFF = 7,
 | 
						|
  TFM_MODAL_SNAP_TOGGLE = 8,
 | 
						|
  TFM_MODAL_AXIS_X = 9,
 | 
						|
  TFM_MODAL_AXIS_Y = 10,
 | 
						|
  TFM_MODAL_AXIS_Z = 11,
 | 
						|
  TFM_MODAL_PLANE_X = 12,
 | 
						|
  TFM_MODAL_PLANE_Y = 13,
 | 
						|
  TFM_MODAL_PLANE_Z = 14,
 | 
						|
  TFM_MODAL_CONS_OFF = 15,
 | 
						|
  TFM_MODAL_ADD_SNAP = 16,
 | 
						|
  TFM_MODAL_REMOVE_SNAP = 17,
 | 
						|
 | 
						|
  /* 18 and 19 used by numinput, defined in transform.h */
 | 
						|
 | 
						|
  TFM_MODAL_PROPSIZE_UP = 20,
 | 
						|
  TFM_MODAL_PROPSIZE_DOWN = 21,
 | 
						|
  TFM_MODAL_AUTOIK_LEN_INC = 22,
 | 
						|
  TFM_MODAL_AUTOIK_LEN_DEC = 23,
 | 
						|
 | 
						|
  TFM_MODAL_EDGESLIDE_UP = 24,
 | 
						|
  TFM_MODAL_EDGESLIDE_DOWN = 25,
 | 
						|
 | 
						|
  /* for analog input, like trackpad */
 | 
						|
  TFM_MODAL_PROPSIZE = 26,
 | 
						|
  /* node editor insert offset (aka auto-offset) direction toggle */
 | 
						|
  TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27,
 | 
						|
};
 | 
						|
 | 
						|
/* Hard min/max for proportional size. */
 | 
						|
#define T_PROP_SIZE_MIN 1e-6f
 | 
						|
#define T_PROP_SIZE_MAX 1e12f
 | 
						|
 | 
						|
bool initTransform(struct bContext *C,
 | 
						|
                   struct TransInfo *t,
 | 
						|
                   struct wmOperator *op,
 | 
						|
                   const struct wmEvent *event,
 | 
						|
                   int mode);
 | 
						|
void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op);
 | 
						|
int transformEvent(TransInfo *t, const struct wmEvent *event);
 | 
						|
void transformApply(struct bContext *C, TransInfo *t);
 | 
						|
int transformEnd(struct bContext *C, TransInfo *t);
 | 
						|
 | 
						|
void setTransformViewMatrices(TransInfo *t);
 | 
						|
void setTransformViewAspect(TransInfo *t, float r_aspect[3]);
 | 
						|
void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy);
 | 
						|
void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag);
 | 
						|
void projectIntView(TransInfo *t, const float vec[3], int adr[2]);
 | 
						|
void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag);
 | 
						|
void projectFloatView(TransInfo *t, const float vec[3], float adr[2]);
 | 
						|
 | 
						|
void applyAspectRatio(TransInfo *t, float vec[2]);
 | 
						|
void removeAspectRatio(TransInfo *t, float vec[2]);
 | 
						|
 | 
						|
struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
 | 
						|
 | 
						|
/*********************** transform_gizmo.c ********** */
 | 
						|
 | 
						|
#define GIZMO_AXIS_LINE_WIDTH 2.0f
 | 
						|
 | 
						|
/* return 0 when no gimbal for selection */
 | 
						|
bool gimbal_axis(struct Object *ob, float gmat[3][3]);
 | 
						|
void drawDial3d(const TransInfo *t);
 | 
						|
 | 
						|
/*********************** TransData Creation and General Handling *********** */
 | 
						|
bool transdata_check_local_islands(TransInfo *t, short around);
 | 
						|
 | 
						|
/********************** Mouse Input ******************************/
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  INPUT_NONE,
 | 
						|
  INPUT_VECTOR,
 | 
						|
  INPUT_SPRING,
 | 
						|
  INPUT_SPRING_FLIP,
 | 
						|
  INPUT_SPRING_DELTA,
 | 
						|
  INPUT_ANGLE,
 | 
						|
  INPUT_ANGLE_SPRING,
 | 
						|
  INPUT_TRACKBALL,
 | 
						|
  INPUT_HORIZONTAL_RATIO,
 | 
						|
  INPUT_HORIZONTAL_ABSOLUTE,
 | 
						|
  INPUT_VERTICAL_RATIO,
 | 
						|
  INPUT_VERTICAL_ABSOLUTE,
 | 
						|
  INPUT_CUSTOM_RATIO,
 | 
						|
  INPUT_CUSTOM_RATIO_FLIP,
 | 
						|
} MouseInputMode;
 | 
						|
 | 
						|
void initMouseInput(
 | 
						|
    TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
 | 
						|
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
 | 
						|
eRedrawFlag handleMouseInput(struct TransInfo *t,
 | 
						|
                             struct MouseInput *mi,
 | 
						|
                             const struct wmEvent *event);
 | 
						|
void applyMouseInput(struct TransInfo *t,
 | 
						|
                     struct MouseInput *mi,
 | 
						|
                     const int mval[2],
 | 
						|
                     float output[3]);
 | 
						|
 | 
						|
void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]);
 | 
						|
void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]);
 | 
						|
void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]));
 | 
						|
 | 
						|
/*********************** Generics ********************************/
 | 
						|
 | 
						|
void initTransDataContainers_FromObjectData(TransInfo *t,
 | 
						|
                                            struct Object *obact,
 | 
						|
                                            struct Object **objects,
 | 
						|
                                            uint objects_len);
 | 
						|
void initTransInfo(struct bContext *C,
 | 
						|
                   TransInfo *t,
 | 
						|
                   struct wmOperator *op,
 | 
						|
                   const struct wmEvent *event);
 | 
						|
void freeTransCustomDataForMode(TransInfo *t);
 | 
						|
void postTrans(struct bContext *C, TransInfo *t);
 | 
						|
void resetTransModal(TransInfo *t);
 | 
						|
void resetTransRestrictions(TransInfo *t);
 | 
						|
 | 
						|
void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options);
 | 
						|
 | 
						|
/* DRAWLINE options flags */
 | 
						|
#define DRAWLIGHT 1
 | 
						|
 | 
						|
void applyTransObjects(TransInfo *t);
 | 
						|
void restoreTransObjects(TransInfo *t);
 | 
						|
void recalcData(TransInfo *t);
 | 
						|
 | 
						|
void calculateCenter2D(TransInfo *t);
 | 
						|
void calculateCenterLocal(TransInfo *t, const float center_global[3]);
 | 
						|
 | 
						|
const TransCenterData *transformCenter_from_type(TransInfo *t, int around);
 | 
						|
void calculateCenter(TransInfo *t);
 | 
						|
 | 
						|
/* API functions for getting center points */
 | 
						|
void calculateCenterBound(TransInfo *t, float r_center[3]);
 | 
						|
void calculateCenterMedian(TransInfo *t, float r_center[3]);
 | 
						|
void calculateCenterCursor(TransInfo *t, float r_center[3]);
 | 
						|
void calculateCenterCursor2D(TransInfo *t, float r_center[2]);
 | 
						|
void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2]);
 | 
						|
bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]);
 | 
						|
 | 
						|
void calculatePropRatio(TransInfo *t);
 | 
						|
 | 
						|
void getViewVector(const TransInfo *t, const float coord[3], float vec[3]);
 | 
						|
 | 
						|
void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot);
 | 
						|
 | 
						|
/*********************** Transform Orientations ******************************/
 | 
						|
 | 
						|
void initTransformOrientation(struct bContext *C, TransInfo *t);
 | 
						|
 | 
						|
/* Those two fill in mat and return non-zero on success */
 | 
						|
bool createSpaceNormal(float mat[3][3], const float normal[3]);
 | 
						|
bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3]);
 | 
						|
 | 
						|
struct TransformOrientation *addMatrixSpace(struct bContext *C,
 | 
						|
                                            float mat[3][3],
 | 
						|
                                            const char *name,
 | 
						|
                                            const bool overwrite);
 | 
						|
bool applyTransformOrientation(const struct TransformOrientation *ts,
 | 
						|
                               float r_mat[3][3],
 | 
						|
                               char r_name[64]);
 | 
						|
 | 
						|
enum {
 | 
						|
  ORIENTATION_NONE = 0,
 | 
						|
  ORIENTATION_NORMAL = 1,
 | 
						|
  ORIENTATION_VERT = 2,
 | 
						|
  ORIENTATION_EDGE = 3,
 | 
						|
  ORIENTATION_FACE = 4,
 | 
						|
};
 | 
						|
#define ORIENTATION_USE_PLANE(ty) ELEM(ty, ORIENTATION_NORMAL, ORIENTATION_EDGE, ORIENTATION_FACE)
 | 
						|
 | 
						|
int getTransformOrientation_ex(const struct bContext *C,
 | 
						|
                               float normal[3],
 | 
						|
                               float plane[3],
 | 
						|
                               const short around);
 | 
						|
int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]);
 | 
						|
 | 
						|
void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data);
 | 
						|
 | 
						|
/* TODO. transform_query.c */
 | 
						|
bool checkUseAxisMatrix(TransInfo *t);
 | 
						|
 | 
						|
#define TRANSFORM_SNAP_MAX_PX 100.0f
 | 
						|
#define TRANSFORM_DIST_INVALID -FLT_MAX
 | 
						|
 | 
						|
/* Temp macros. */
 | 
						|
 | 
						|
#define TRANS_DATA_CONTAINER_FIRST_OK(t) (&(t)->data_container[0])
 | 
						|
/* For cases we _know_ there is only one handle. */
 | 
						|
#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t) \
 | 
						|
  (BLI_assert((t)->data_container_len == 1), (&(t)->data_container[0]))
 | 
						|
 | 
						|
#define FOREACH_TRANS_DATA_CONTAINER(t, th) \
 | 
						|
  for (TransDataContainer *tc = (t)->data_container, \
 | 
						|
                          *tc_end = (t)->data_container + (t)->data_container_len; \
 | 
						|
       th != tc_end; \
 | 
						|
       th++)
 | 
						|
 | 
						|
#define FOREACH_TRANS_DATA_CONTAINER_INDEX(t, th, i) \
 | 
						|
  for (TransDataContainer *tc = ((i = 0), (t)->data_container), \
 | 
						|
                          *tc_end = (t)->data_container + (t)->data_container_len; \
 | 
						|
       th != tc_end; \
 | 
						|
       th++, i++)
 | 
						|
 | 
						|
#endif
 |