/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup DNA
 */

#pragma once

#include "DNA_ID.h"
#include "DNA_listBase.h"

#include "BLI_enum_flags.hh"

namespace blender {

struct AnimData;
struct BoundBox;
struct Material;

/** #MetaBall::texspace_flag */
enum eMetaBall_TexSpaceFlag : char {
  MB_TEXSPACE_FLAG_AUTO = 1 << 0,
};
ENUM_OPERATORS(eMetaBall_TexSpaceFlag)

/** #MetaBall::flag */
enum eMetaBall_Flag : char {
  MB_UPDATE_ALWAYS = 0,
  MB_UPDATE_HALFRES = 1,
  MB_UPDATE_FAST = 2,
  MB_UPDATE_NEVER = 3,
};

/** #MetaBall::flag2 */
enum eMetaBall_Flag2 : char {
  MB_DS_EXPAND = 1 << 0,
};
ENUM_OPERATORS(eMetaBall_Flag2)

/** #MetaElem::type */
enum eMetaElem_Type : short {
  MB_BALL = 0,
  MB_TUBEX = 1, /* Deprecated. */
  MB_TUBEY = 2, /* Deprecated. */
  MB_TUBEZ = 3, /* Deprecated. */
  MB_TUBE = 4,
  MB_PLANE = 5,
  MB_ELIPSOID = 6,
  MB_CUBE = 7,
};

#define MB_TYPE_SIZE_SQUARED(type) ((type) == MB_ELIPSOID)

/** #MetaElem::flag */
enum eMetaElem_Flag : short {
  MB_SELECT = (1 << 0),
  MB_NEGATIVE = 1 << 1,
  MB_HIDE = 1 << 3,
  MB_SCALE_RAD = 1 << 4,
};
ENUM_OPERATORS(eMetaElem_Flag)

struct MetaElem {
  struct MetaElem *next = nullptr, *prev = nullptr;

  /** Bound Box of MetaElem. */
  struct BoundBox *bb = nullptr;

  eMetaElem_Type type = MB_BALL;
  eMetaElem_Flag flag = {};
  char _pad[4] = {};
  /** Position of center of MetaElem. */
  float x = 0, y = 0, z = 0;
  /** Rotation of MetaElem (MUST be kept normalized). */
  float quat[4] = {};
  /** Dimension parameters, used for some types like cubes. */
  float expx = 0;
  float expy = 0;
  float expz = 0;
  /** Radius of the meta element. */
  float rad = 0;
  /** Temp field, used only while processing. */
  float rad2 = 0;
  /** Stiffness, how much of the element to fill. */
  float s = 0;
  /** Old, only used for backwards compatibility. use dimensions now. */
  float len = 0;

  /** Matrix and inverted matrix. */
  float *mat = nullptr, *imat = nullptr;
};

struct MetaBall {
#ifdef __cplusplus
  /** See #ID_Type comment for why this is here. */
  static constexpr ID_Type id_type = ID_MB;
#endif

  ID id;
  struct AnimData *adt = nullptr;

  ListBaseT<MetaElem> elems = {nullptr, nullptr};
  /** Not saved in files, note we use pointer for editmode check. */
  ListBaseT<MetaElem> *editelems = nullptr;

  /* material of the mother ball will define the material used of all others */
  struct Material **mat = nullptr;

  /** Flag is enum for updates, flag2 is bit-flags for settings. */
  eMetaBall_Flag flag = MB_UPDATE_ALWAYS;
  eMetaBall_Flag2 flag2 = {};
  short totcol = 0;
  char texspace_flag = MB_TEXSPACE_FLAG_AUTO;
  char _pad[2] = {};

  /**
   * ID data is older than edit-mode data (TODO: move to edit-mode struct).
   * Set #Main.is_memfile_undo_flush_needed when enabling.
   */
  char needs_flush_to_id = 0;

  float texspace_location[3] = {};
  float texspace_size[3] = {1, 1, 1};

  /** Display and render res. */
  float wiresize = 0.4f, rendersize = 0.2f;

  /* bias elements to have an offset volume.
   * mother ball changes will effect other objects thresholds,
   * but these may also have their own thresh as an offset */
  float thresh = 0.6f;

  char _pad0[4] = {};

  /** The active meta-element (used in edit-mode). */
  MetaElem *lastelem = nullptr;
};

}  // namespace blender
