A Geometrical Challenge

Pyth, 40 36 34 32 bytes

-1 byte by @isaacg


A semicolon inside a lambda is now the lambda variable's global value, a feature that saves one byte.

                         Implicit: z = input
JstPz                    J = size.
_W }\+z                  Reverse if "+" in z
j l# m                J  Join the nonempty lines in map lambda d:... over range(J)
      .[J            ;   Pad the following with spaces (;) to length J
         *\*               "*", this many times:
            -J*}\tzyd        J if "t" not  in z,
                             otherwise the correct number for a triangle.

Try it here.

Test suite.

Pyth, 38 bytes


Test suite

Basically as straightforward as it gets. I wish I could combine some of the logic for the two shapes, but currently it's separate.

Python 2, 106 bytes

for i in[range(1,n+1,2),n*[n]][s<'t'][::2*('+'in s)-1]:print('*'*i).center(n)

The output is a perfect rectangle, with each line padded with trailing spaces, which I'm assuming is okay based on the comments in the OP.

Note: I'm still never sure whether input is allowed in Python 2 for problems like these...