% !TeX root = ./test.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This is the TikZbricks package
% A package to draw bricks with tikz
% Maintained by samcarter
%
% Project repository and bug tracker:
% https://github.com/samcarter/TikZbricks
%
% Released under the LaTeX Project Public License v1.3c or later
% See https://www.latex-project.org/lppl.txt
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ProvidesPackage{tikzbricks}[2024/12/16 version v0.6 Drawing bricks with TikZ]

\RequirePackage{tikz}
\RequirePackage{tikz-3dplot}
\RequirePackage{xkeyval}

% setting a default viewpoint
\tdplotsetmaincoords{70}{160}

% setting default values
\DeclareOptionX{color}[red]{\def\brick@default@color{#1}}
\DeclareOptionX{frontcolor}[\brick@color!60]{\def\brick@default@frontcolor{#1}}
\DeclareOptionX{topcolor}[\brick@color!40]{\def\brick@default@topcolor{#1}}
\DeclareOptionX{sidecolor}[\brick@color]{\def\brick@default@sidecolor{#1}}
\DeclareOptionX{studcolor}[\brick@color]{\def\brick@default@studcolor{#1}}
\DeclareOptionX{brickheight}[1.3]{\def\brick@default@height{#1}}
\DeclareOptionX{bricklength}[1.0]{\def\brick@default@length{#1}}
\DeclareOptionX{bricktext}[]{\def\brick@default@facetext{#1}}
\DeclareOptionX{brickwidth}[1.0]{\def\brick@default@width{#1}}
\DeclareOptionX{studradius}[0.35]{\def\brick@default@radius{#1}}
\DeclareOptionX{studheight}[0.3]{\def\brick@default@studheight{#1}}
\DeclareOptionX{studtext}[]{\def\brick@default@text{#1}}


\ExecuteOptionsX{color,frontcolor,topcolor,sidecolor,studcolor,brickheight,bricklength,bricktext,brickwidth,studradius,studheight,studtext}

\ProcessOptionsX

% counter to dermine the position of a brick in a wall
\newcounter{brickx}
\newcounter{bricky}
\newcounter{brickz}

% draw a standalone brick
% 1: optional argument
% 2: lenght
% 3: width
\newcommand*{\brick}[3][]{%
  \setcounter{brickx}{0}%
  \setcounter{bricky}{0}%
  \setcounter{brickz}{0}%
  \begin{scope}%
    \tikzset{/brick/.cd,#1}%
    \brick@draw{#2}{#3}%
  \end{scope}%
}

% draw a brick in a wall
% 1: optional argument
% 2: lenght
% 3: width
\newcommand*{\wallbrick}[3][]{%
  \begin{scope}%
    \tikzset{/brick/.cd,#1}%
    \brick@draw{#2}{#3}%
  \end{scope}%
  \addtocounter{brickx}{#2}%
}

% envrinoment to arange the bricks in a wall
% 1: optional argument passed to the tikzpicture
\newenvironment{wall}[1][]{%
  \setcounter{brickx}{0}%
  \setcounter{bricky}{0}%
  \setcounter{brickz}{0}%
  \newcommand{\newrow}{%
    \setcounter{brickx}{0}%
    \addtocounter{brickz}{1}%
  }%
  \begin{tikzpicture}[#1]
}{%
  \end{tikzpicture}%
}

\tikzset{
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  % Pass unknown keys on to tikz
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  /brick/.search also={/tikz,/pgf},
  /brick/.cd,
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  % brick options
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  color/.code         = \def\brick@color{#1},
  color               = \brick@default@color,
  frontcolor/.code    = \def\brick@frontcolor{#1},
  frontcolor          = \brick@default@frontcolor,
  topcolor/.code      = \def\brick@topcolor{#1},
  topcolor            = \brick@default@topcolor,
  sidecolor/.code     = \def\brick@sidecolor{#1},
  sidecolor           = \brick@default@sidecolor,
  studcolor/.code     = \def\brick@studcolor{#1},
  studcolor           = \brick@default@studcolor,
  brickheight/.code   = \def\brick@height{#1},
  brickheight         = \brick@default@height,
  bricklength/.code   = \def\brick@length{#1},
  bricklength         = \brick@default@length,
  bricktext/.code     = \def\brick@facetext{#1},
  bricktext           = \brick@default@facetext,
  brickwidth/.code    = \def\brick@width{#1},
  brickwidth          = \brick@default@width,
  studradius/.code    = \def\brick@radius{#1},
  studradius          = \brick@default@radius,
  studheight/.code    = \def\brick@studheight{#1},
  studheight          = \brick@default@studheight,
  studtext/.code      = \def\brick@text{#1},
  studtext            = \brick@default@text,
}

\newcommand{\brick@draw}[2]{%
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  % store the current scale factor
  % from https://github.com/samcarter/tikzlings/issues/3#issuecomment-461373494
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \pgfgettransformentries{\tmpscaleA}{\tmpscaleB}{\tmpscaleC}{\tmpscaleD}{\tmp}{\tmp}%
  \pgfmathsetmacro{\scalingfactor}{sqrt(abs(\tmpscaleA*\tmpscaleD-\tmpscaleB*\tmpscaleC))*sqrt(abs((\pgf@xx/1cm)*(\pgf@yy/1cm)-(\pgf@xy/1cm)*(\pgf@yx/1cm)))}%
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %
  % Drawing the brick
  %
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \begin{scope}[tdplot_main_coords]

    % Drawing faces
   \pgfmathparse{sign(sin(\tdplotmainphi))}
   \let\brick@sin\pgfmathresult
   \pgfmathparse{sign(cos(\tdplotmainphi))}
   \let\brick@cos\pgfmathresult

    \ifnum\brick@sin<0
      % Right
      \fill[\brick@sidecolor,thick]
        (
          \brick@length*\value{brickx},
          \brick@width*\value{bricky},
          \brick@height*\value{brickz}
        )
        -- ++(0,0,\brick@height)
        -- ++(0,\brick@width*#2,0)
        -- ++(0,0,-\brick@height)
        -- cycle;
    \else
      % Left
      \fill[\brick@sidecolor,thick]
        (
          {\brick@length*(#1+\value{brickx})},
          \brick@width*\value{bricky},
          \brick@height*\value{brickz}
        )
        -- ++(0,0,\brick@height)
        -- ++(0,\brick@width*#2,0)
        -- ++(0,0,-\brick@height)
        -- cycle;
    \fi

    \ifnum\brick@cos<0
      % Front
      \fill[\brick@frontcolor,thick]
        (
          \brick@length*\value{brickx},
          {\brick@width*(#2+\value{bricky})},
          \brick@height*\value{brickz}
        )
        -- ++(\brick@length*#1,0,0)
        -- ++(0,0,\brick@height)
        -- ++(-\brick@length*#1,0,0)
        -- cycle;

        \node[align=center, transform shape, canvas is zx plane at y=0, rotate=-90] at (
            \brick@length*\value{brickx} + 0.5*\brick@length*#1,
            {\brick@width*(#2+\value{bricky})},
            \brick@height*\value{brickz} + 0.5*\brick@height
        ) {\brick@facetext};

    \else
      % Back
      \fill[\brick@frontcolor,thick]
        (
          \brick@length*\value{brickx},
          \brick@width*\value{bricky},
          \brick@height*\value{brickz}
        )
        -- ++(\brick@length*#1,0,0)
        -- ++(0,0,\brick@height)
        -- ++(-\brick@length*#1,0,0)
        -- cycle;
    \fi

    % Top
    \fill[\brick@topcolor,thick]
      (
        \brick@length*\value{brickx},
        \brick@width*\value{bricky},
        {\brick@height*(1+\value{brickz})}
      )
      -- ++(0,\brick@width*#2,0)
      -- ++(\brick@length*#1,0,0)
      -- +(0,-\brick@width*#2,0)
      -- cycle;



    % Drawing studs
    \foreach \x in {1,...,#1}{
      \foreach \y in {1,...,#2}{

        % Bottom circle
        \fill[\brick@studcolor]
          (
            {\brick@length*(\x-0.5+\value{brickx})},
            {\brick@width*(\y-0.5+\value{bricky})},
            {\brick@height*(1+\value{brickz})}
          )
          circle [radius=\brick@radius];

        % Rectangular stem
        \fill[\brick@studcolor]
          (
            {\brick@length*(\x-0.5+\value{brickx})},
            {\brick@width*(\y-0.5+\value{bricky})},
            {\brick@height*(1+\value{brickz})}
          )
          ++(canvas cs:x=-\brick@radius/0.35*10)
          -- ++(canvas cs:y=\brick@studheight*17.8)
          -- ++(canvas cs:x=\brick@radius/0.35*20)
          -- ++(canvas cs:y=-\brick@studheight*17.8);

        % Top circle with text
        \fill[\brick@topcolor]
          (
            {\brick@length*(\x-0.5+\value{brickx})},
            {\brick@width*(\y-0.5+\value{bricky})},
            {\brick@height*(1+\value{brickz})}
          )
          ++(canvas cs:y=\brick@studheight*17.8)
          circle [radius=\brick@radius]
          node[\brick@color,scale=\scalingfactor*0.5, font=\sffamily] {\brick@text};

      }
    }

  \end{scope}
}