Struct, Array and Pointer?

Started by Ronsen, Mon 26/01/2015 16:07:34

Previous topic - Next topic

Ronsen

Don't hurt me I try to figure out how pointers, strucs and arrays work and I think a need a little hand here. The search brings up a lot about pointer, arrays and stuff, but it made me even more confuse. I'm trying to fill in a simple ListBox, which actually works, but how do I make it to choose be
array FiltersDX5 or FiltersD3D9? Is a pointer here the right direction?

I'm trying to write my code as a module ;)

Code: ags

// *.ash 

// new Setup module header

#define LST_DX5_LIST 7

#define LST_D3D9_LIST 10


struct GfxFilter {
  String name;
  String filter;
  String filter_scaling;
};

GfxFilter FiltersDX5[LST_DX5_LIST];
GfxFilter FiltersD3D9[LST_D3D9_LIST];

export FiltersDX5; export FiltersD3D9;



Code: ags


// *.asc
// new module script
   .....
   ......
   
   String driver = ini.Read("graphics", "driver", "DX5");

  // how to set a pointer??? to FiltersDX5[] array
  int aVariableArraySize = LST_DX5_LIST;
  if (driver == "D3D9") {
    //change pointer??? to FiltersD3D9 array...
    aVariableArraySize = LST_D3D9_LIST;
  }
  
  int i = 0;
  while (i < aVariableArraySize) {
    lstFilter.AddItem(Filters???[i].name);
    i++;
  }
  
  ....
  .....

monkey0506

#1
It depends on which version of AGS you're using, but as of the latest stable version (AGS 3.3.3), there are no pointers to custom user struct types. This is actually introduced in the up-coming version (AGS 3.4.0), but currently (AGS 3.4.0.3) you cannot have both pointers to a custom struct type and pointers within that struct. This would prevent you from having a pointer to your type (or a dynamic array of your type) while storing Strings within them.

You could use the old-style string functions like this:

Spoiler
Code: ags
// *.ash

#define LST_DX5_LIST 7
#define LST_D3D9_LIST 10

managed struct GfxFilter
{
  char name[200];
  char filter[200];
  char filter_scaling[200];
};

// NOTE: **NEVER** define struct instances in a header file!! ONLY import them! 
import GfxFilter* FiltersDX5[]; // use these as dynamic arrays, so you can get a pointer to the array
import GfxFilter* FiltersD3D9[];


Code: ags
// *.asc
// import old-style string functions
import void StrCopy(string, const string);
import int StrLen(const string);

GfxFilter* FiltersDX5[];
GfxFilter* FiltersD3D9[];
export FiltersDX5;
export FiltersD3D9;

function game_start()
{
  // initialize arrays
  FiltersDX5 = new GfxFilter[LST_DX5_LIST];
  FiltersD3D9 = new GfxFilter[LST_D3D9_LIST];
  int i;
  for (i = 0; (i < LST_DX5_LIST) || (i < LST_D3D9_LIST); i++)
  {
    if (i < LST_DX5_LIST)
    {
      FiltersDX5[i] = new GfxFilter;
    }
    if (i < LST_D3D9_LIST)
    {
      FiltersD3D9[i] = new GfxFilter;
    }
  }
  // populate array members
  String buffer;
  buffer = "SomeFilterName";
  StrCopy(FiltersDX5[0].name, buffer); // etc.
}

String CharArrayToString(const string buffer)
{
  String s = buffer;
  return s;
}

void DoSomething()
{
  String driver = ini.Read("graphics", "driver", "DX5");
  GfxFilter *filters[] = FiltersDX5;
  int aVariableArraySize = LST_DX5_LIST;
  if (driver == "D3D9")
  {
    filters = FiltersD3D9;
    aVariableArraySize = LST_D3D9_LIST;
  }
  int i = 0;
  while (i < aVariableArraySize)
  {
    String name = CharArrayToString(filters[i].name); // copy the struct member into a String to take full advantage of any new-style String functions
    lstFilter.AddItem(name);
    i++;
  }
}
[close]

That being said, if you're trying to change the graphics filter settings at run-time, just be aware that it won't work. The AGS engine currently can only change filters when the game is first launched.

Edit: Correction - The above code does not work, producing a segfault when trying to access the member arrays using StrCopy. The characters could be manually copied into the arrays, but that loses so much of the efficiency of the code that other solutions should be utilized instead.

Ronsen

Thank you very much monkey!!! Yes I know, I need to restart the engine to get all my changes to the acsetup.cfg file working.
But I have most of the winsetup settings now in a gui/module so I can change them easy In-Game under Linux. I already use the 3.4.0.3 build ;) It would be nice to know how it will change in the new build...just if you have time.

Crimson Wizard

Quote from: Ronsen on Mon 26/01/2015 19:36:26
Thank you very much monkey!!! Yes I know, I need to restart the engine to get all my changes to the acsetup.cfg file working.
But I have most of the winsetup settings now in a gui/module so I can change them easy In-Game under Linux. I already use the 3.4.0.3 build ;) It would be nice to know how it will change in the new build...just if you have time.
Now we only need to introduce script commands to change gfx resolutions and filters at runtime ....

monkey0506

I was actually curious about doing that. Does Allegro 4 allow that to be done? I thought that it wasn't possible with A4.

Ronsen

Unfortunately I still have some trouble with this line:

Code: ags

 GfxFilter *array = FiltersDX5;


It says : Type mismatch: cannot convert 'Gfxfilter[]' to 'Gfxfilter*' :/


monkey0506

#6
Yeah, sorry. That was a mistake. I edited the post above.

I amended a few other things as well, such as incorrectly converting the char array into a new-style String. The above code should now work as intended.

Ronsen

Thank you a lot but i still have some trouble and it's btw already over my head. I get back to my level and put everything in 1 array...which I didn't want to do...but hey

Code: AGS

// new Setup module header
#define FILTER_MAX 17

struct GfxFilter {
  String name;
  String filter;
  String filter_scaling;
  String driver;
};

import GfxFilter filters[FILTER_MAX];


Code: AGS

  GfxFilter filters[FILTER_MAX];
  export filters;
....
  String driver = ini.Read("graphics", "driver", "DX5");
  String filter = ini.Read("graphics", "filter", "None");
  String filter_scaling = ini.Read("graphics", "filter_scaling", "1")
.....
   // DX5 gfxfilter (i know this could be better)
  filters[0].name = "StdScale";
  filters[0].filter = "StdScale";
  filters[0].filter_scaling = "1";
  filters[0].driver = "DX5";
 
  filters[1].name = "StdScale2";
  filters[1].filter = "StdScale";
  filters[1].filter_scaling = "2";
  filters[1].driver = "DX5";
  
  filters[2].name = "StdScale3";
  filters[2].filter = "StdScale";
  filters[2].filter_scaling = "3";
  filters[2].driver = "DX5";
  
  filters[3].name = "StdScale4";
  filters[3].filter = "StdScale";
  filters[3].filter_scaling = "4";
  filters[3].driver = "DX5";
  
  filters[4].name = "StdScaleMax";  
  filters[4].filter = "StdScale";
  filters[4].filter_scaling = "max";
  filters[4].driver = "DX5";
  
  filters[5].name = "Hq2x";  
  filters[5].filter = "Hq2x";
  filters[5].filter_scaling = "2";
  filters[5].driver = "DX5";
  
  filters[6].name = "Hq3x";
  filters[6].filter = "Hq3x";
  filters[6].filter_scaling = "3";
  filters[6].driver = "DX5";
  
  // D3D9 gfxfilters
  
  filters[7].name = "StdScale";
  filters[7].filter = "StdScale";
  filters[7].filter_scaling = "1";
  filters[7].driver = "D3D9";
  
  filters[8].name = "StdScale2";
  filters[8].filter = "StdScale";
  filters[8].filter_scaling = "2";
  filters[8].driver = "D3D9";
  
  filters[9].name = "StdScale3";
  filters[9].filter = "StdScale";
  filters[9].filter_scaling = "3";
  filters[9].driver = "D3D9";
  
  filters[10].name = "StdScale4";
  filters[10].driver = "D3D9";
  filters[10].filter = "StdScale";
  filters[10].filter_scaling = "4";
  
  filters[11].name = "StdScaleMax";
  filters[11].filter = "StdScale";
  filters[11].filter_scaling = "max";
  filters[11].driver = "D3D9";
  
  filters[12].name = "Linear";
  filters[12].filter = "Linear";
  filters[12].filter_scaling = "1";
  filters[12].driver = "D3D9";
  
  filters[13].name = "Linear2";
  filters[13].driver = "D3D9";
  filters[13].filter = "Linear";
  filters[13].filter_scaling = "2";
  
  filters[14].name = "Linear3";
  filters[14].filter = "Linear";
  filters[14].filter_scaling = "3";
  filters[14].driver = "D3D9";
  
  filters[15].name = "Linear4";
  filters[15].filter = "Linear";
  filters[15].filter_scaling = "4";
  filters[15].driver = "D3D9";
  
  filters[16].name = "LinearMax";
  filters[16].filter = "Linear";
  filters[16].filter_scaling = "max";
  filters[16].driver = "D3D9";

  lstFilter.Clear(); // Clear the Listbox first

  // Fill in the Listbox
  int i = 0;
  while (i < FILTER_MAX) {
    if (filters[i].driver == driver) {
      lstFilter.AddItem(filters[i].name);
    }
    i++;
  }
  // Search for the Array[ID] and select it in the ListBox
  int id = 0;
  while (id < FILTER_MAX) {
    if ((filters[id].filter == filter) && (filters[id].filter_scaling == filter_scaling) && (filters[id].driver == driver)) {
      lstFilter.SelectedIndex = id;
      lstFilter.TopItem = id;
      lstFilter.ScrollUp(); // Bring it to the center ;)      
    }
    id++;
  }


monkey0506

Hmm, yes, sorry about that. I created this post while I was in class and didn't have access to AGS. I forgot that since the two GfxFilter arrays are actually arrays of pointers that the individual items in the arrays also have to be initialized.

And then I keep getting segmentation faults when trying to use StrCopy on the item's char[200] arrays, although I can manually copy them in a simple for loop. It now occurs to me that AGS never did allow old-style strings as members of a struct, so I wonder if there is some underlying cause as to why it can't read the address of the array properly. In any case, I redact my proposed solution as it doesn't actually work. Sorry again for the confusion.

SMF spam blocked by CleanTalk