Using enumeral arrays

I have an array[0…9] of string:

    Cursor[1] := 'mouse-hand';
    Cursor[2] := 'mouse-talk';
    Cursor[3] := 'mouse-walk';
    Cursor[4] := 'mouse-inventory';
    Cursor[5] := 'mouse-arrowleft';
    Cursor[6] := 'mouse-arrowright';
    Cursor[7] := 'mouse-arrowup';
    Cursor[8] := 'mouse-arrowdown';
    Cursor[9] := 'mouse-stopsign';

but would like to replace it with enumeral type like in the pascal introduction manual:

``type
TAnimalKind = (akDuck, akCat, akDog);
 TAnimalNames = array [TAnimalKind] of string;

So:

TMouseCursors = (mouse-eye, mouse-hand, mouse-talk, mouse-walk);
TCursor = array(TMouseCursors) of string;

var Cursor: TCursor;

But how can I access this?

Image := Cursor[1];

Gives an error.

You cannot safely mix the two approaches (you can still unsafely mix those).

type
  TMyCursor = (mcEye, mcHand, mcTalk, mcWalk); //note, it's a good idea to avoid using minus sign "-" in enum names, I'd be quite surprised if it'd work.
var
  MyArray: array [TMyCursor] of TCastleScene; // Note square brackets "[...]" and it may be a better idea to directly reference a TCastleScene in this case, not some string.
...
CursorScene := MyArray[mcEye]; // i.e. you have to reference enum directly.
// You can also reference to TMyCursor by
CursorScene := MyArray[TMyCursor(0)];
// however, be aware that it may end in unexpected result in some situations. As in "not safe". E.g. if you reorder the cursors in TMyCursor - you'll get a weird, hard-to-debug bug.
1 Like

Thanks.
I choose the second option, as the ‘cursor order’ will remain the same.
The idea is to right click mouse through the options.
The array is a string because there is only 1 spritescreen with an xml file containing the names that are accessed by Playanimation.
But now calling the name in the xml it does not work; it appears the contents (mcHand etc) are not read. This is what I have:

type TGamemouse = class(TComponent)
 private
   Scene: TCastleScene;
   NR: integer;
   type
     TCursor = (mcEye, mcHand, mcTalk, mcWalk);
   var
  CursorArray: array [TCursor] of string;
 end;                  


PlayerMouse: TGamemouse; 

procedure TStatePlay.CreatePlayerMouse;
begin
  PlayerMouse := TGamemouse.Create(PlayerMouse);
  Scene := DesignedComponent ('Mouse') as TCastleScene;
  Scene.Cursor:= mcForceNone;
end;           


if Event.IsMouseButton(buttonRight)then
begin
  inc(PlayerMouse.NR);  // cycle through the options
  if PlayerMouse.NR = 4 then PlayerMouse.NR := 0;
  PlayerMouse.Scene.PlayAnimation(PlayerMouse.CursorArray[PlayerMouse.TCursor(PlayerMouse.NR)], true);
end;

xml file is:

<?xml version="1.0" encoding="utf-8"?>
<TextureAtlas imagePath="mouse-icons.png">
  <SubTexture x="0" y="200" fps="8" name="mcEye" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="50" y="200" fps="8" name="mcHand" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="100" y="200" fps="8" name="mcTalk" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="150" y="200" fps="8" name="mcWalk" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="200" y="200" fps="8" name="mouse-inventory" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="0" y="150" fps="8" name="mcArrowleft" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="50" y="150" fps="8" name="mcArrowright" width="50" height="50"/>
  <SubTexture x="100" y="150" fps="8" name="mcArrowup" width="50" height="50"/>
  <SubTexture x="150" y="150" fps="8" name="mcArrowdown" width="50" frameX="0" frameY="0" height="50" frameWidth="50" frameHeight="50"/>
  <SubTexture x="200" y="150" fps="8" name="mcStopsign" width="50" height="50"/>
</TextureAtlas>

Testing here, the Starling XML you show works, it has the animations you indicated (opening in view3dscene).

( I used a dummy texture, don’t pay attention to it, just see that animation list corresponds to your XML names )

As for enums: while you can convent between enum <-> integers back and forth (as mentioned on Modern Object Pascal Introduction for Programmers , TAnimalKind(MyInteger) or Ord(High(TAnimalKind)) … but this is a bit hacky. If you find yourself constantly converting enum <-> integers, it may mean you don’t really want enums, and instead should just use integers. The point of enums is that they (at least usually) act as “opaque” type and you don’t need to think about their numerical value.

Cycling can be done on enums without any typecasts, use Low, High and Succ standard Pascal constructs:

if MyCursor = High(MyCursor) then
  MyCursor := Low(MyCursor)
else
  MyCursor := Succ(MyCursor);