//structure.inc /* I have no idea how this is gonna work, but basically it should read sorta like this: interfaceClass MyInterfaceClass { member1, member2, member3, methoda, //may be virtual functions (i.e. null) methodb, methodc } class MyClass::MyInterfaceClass { //type specific members, i.e. invisible to anything interfacing with MyInterfaceClass member4, member5, //implementations of interface functions methoda, methodb, methodc, //type specific methods methodd, methode } interfaceArray = new MyInterfaceClass[numInterfaces]; interfaceArray[0] = new MyClass; interfaceArray[0].methoda( param, param ); || \/ MyClass::methoda ( param, param ) { //we know this is of MyClass type v = this.member4; //read a private member u = this.member1; //read a public member. } */ #include "scratchfile.inc" #include "morestrings.inc" //hmm... //memory controls: change these values to suit your needs. #declare maxInstances = 100; //an array of this many structs will be created each time you define a struct #declare maxStructTypes = 20; //we use this to keep track of information about each struct, e.g. name of struct type. //global structure trackers #declare newStructHandle = 0; #declare structNames = array[maxStructTypes]; //a simple structure: #macro Struct(sStructName, //the name by which you will refer to this struct sStructSpec) //a whitespace seperated list of member variable names. //create an array for each member variable. #local sVar = GetFirstWord(sStructSpec); #while (strlen(sVar) != 0) scratchParse(concat("#declare ",sStructName,"_",sVar," = array[",str(maxInstances,0,0),"];\n")) //types are implicit in pov, so we don't need to worry about them. #local sVar = GetNextWord(sStructSpec); #end //create management values for this struct: scratchParse(concat("#declare new_",sStructName," = 0;\n")) //set creation index to 0 //store the name of this struct #declare structNames[newStructHandle] = sStructName; #declare newStructHandle = newStructHandle + 1; #end //macros to extract the handle and index from an instance value. #macro structHandle(a) int(a / maxInstances) #end #macro structIndex(a) mod(a, maxInstances) #end //create an instance of a structure #macro new(sStructName) #local handle = 0; #while ( strcmp(structNames[handle], sStructName) ) //if you get an error here, your struct name could not be found. make sure it matches the name passed to Struct() #local handle = handle + 1; #end scratchParse(concat("#declare index = new_",sStructName,";\n")) //read what the index was. scratchParse(concat("#declare new_",sStructName," = new_",sStructName," + 1;\n")) //increment it #if ( index >= maxInstances ) #error "ran out of instances" #end (index + maxInstances*handle) //return the index to the structure we just created, combined with a handle for this struct type #end //delete an instance. //note: this will mess up anything that's trying to hang onto a "pointer", so be careful when calling this function. #macro delete(i) #local structName = structNames[structHandle(i)]; #local i = structIndex(i); scratchParse(concat("#declare numStructs = new_",structName,";\n")) //read what the index was. scratchParse(concat("#declare new_",structName," = new_",structName," - 1;\n")) //decrement it /* //do very basic memory management, copy everything after it in the array back by one. #while ( i < numStructs-1 ) structCopy( sStructName, i, i+1 ); *this function doesn't exist, and I've thrown out the information it would need! So the create function needs to keep that info somewhere so structs can be deleted #declare structHandle[i] = structHandle[i+1]; #local i = i + 1; #end */ #end //set and get functions, // instead of obj.var = val, do set(obj,val,val) // instead of something = obj.var, do something = get(obj,val) #macro set ( i, member, value ) scratchParse(concat("#declare ",structNames[structHandle(i)],"_",member,"[structIndex(i)] = value;\n")) #end #macro get ( i, member ) scratchParse(concat(""structNames[structHandle(i)],"_",member,"[structIndex(i)]")) #end //okay, let's test it: Struct( "MyStruct","vectorVariable, floatVariable, stringVariable") //create some objects of this type, test they're okay, then DESTROY THEM1!!! mawahahaha #declare bob = new("MyStruct"); #declare phylis = new("MyStruct"); set(bob,"vectorVariable",x+71) set(phylis,"floatVariable",0.14) set(bob,"stringVariable","tuesday") //now, something a little more advanced. //phylis.vectorVariable = bob.vectorVariable * phylis.floatVariable; set(phylis,"vectorVariable", get(bob,"vectorVariable") * get(phylis,"floatVariable") ) //bob.floatVariable = dot(phylis.vectorVariable, bob.vectorVariable) set(bob,"floatVariable", vdot(get(bob,"vectorVariable"), get(phylis,"vectorVariable")) ) //some string functions set(phylis,"stringVariable", substr(get(bob,"stringVariable"),5,3) ) //lets see what we've got. #debug concat("bob <",str(MyStruct_vectorVariable[structIndex(bob)].x,0,2),",",str(MyStruct_vectorVariable[structIndex(bob)].y,0,2),",",str(MyStruct_vectorVariable[structIndex(bob)].z,0,2),"> ", str(MyStruct_floatVariable[structIndex(bob)],0,2)," ",MyStruct_stringVariable[structIndex(bob)],"\r\f") #debug concat("phylis <",str(MyStruct_vectorVariable[structIndex(phylis)].x,0,2),",",str(MyStruct_vectorVariable[structIndex(phylis)].y,0,2),",",str(MyStruct_vectorVariable[structIndex(phylis)].z,0,2),"> ", str(MyStruct_floatVariable[structIndex(phylis)],0,2)," ",MyStruct_stringVariable[structIndex(phylis)],"\f\r") //finally, delete them in the wrong order. delete(bob) #debug concat("\n\nafter deleting bob: phylis <",str(MyStruct_vectorVariable[structIndex(phylis)].x,0,2),",",str(MyStruct_vectorVariable[structIndex(phylis)].y,0,2),",",str(MyStruct_vectorVariable[structIndex(phylis)].z,0,2),"> ", str(MyStruct_floatVariable[structIndex(phylis)],0,2)," ",MyStruct_stringVariable[structIndex(phylis)],"\r\f") delete(phylis)