Custom Types (Direct access)
Blitz3D Forums/Blitz3D Programming/Custom Types (Direct access)
| ||
Hi Guys, I steered away from custom types for months (using dims etc). but I finally got my head around them and rewrote a huge chunk of my code using them. it works fine but I have one question (that I couldnt find a direct answer to in all the posts). Right now a create new objects in the usual way. If I want to query them I have to do a for X.X = each object if..... next Is there a way to query it like a variable where I say (for my specific example I'm trying to find the x and y position of a particular objects target). I've added an ID number to each object so object 1's target might be object 3 and so on. For body.body = Each body For target.body= Each body If body\target = target\ID target_x=target\x target_y=target\y End If Next ship_x=body\x ship_y=body\y EndIf Next which is a little time consuming. but what I'd liek to do is something like:- target_x=body\x (body\target) like calling an array location. possible (not like that I know) but at all? Cheers, |
| ||
You can make one of the fields a 'body'type body field target.body end type b.body = new body c.body = new body c\target = b Or you can make an array of 'bodies' type body field x, y end type dim body_array.body(100) body_array(0) = new body body_array(1) = new body body_array(2) = new body |
| ||
You can make one of the fields a 'body' type body field target.body end type b.body = new body c.body = new body c\target = b I recommend this approach. Further, you don't even need the field to be an Instance of 'body' Type, but if you feel confident enough, you can just use the 'Handle' of the instance. type body Field Target Field X,Y end type b.body = new body c.body = new body c\target = Handle(b.Body) To retrieve the actual Instance from the handle, just use Object: [code] ThisInstance.Body=Object.Body(TargetHandle) ; Or rather: ThisBody.Body=Object.Body(MyInstance\Target) |
| ||
"Object" and "Handle" (which are obscure, undocumented but highly useful commands) are what you need to directly save and retrieve a specific type handle without having to loop through all of them. Malice already showed how, but here I can give my own bit of an example: Type mytype Field A,B,C End Type Function Create_a_Mytype(A,B,C) Local this.mytype this.mytype=New mytype this\A=A this\B=B this\C=C Return Handle(this); we tell the function to return the handle for this type, so we can store it somewhere for later use End Function Function Edit_ThisMyType(savedhandle,A,B,C) Local this.mytype If Object.mytype(savedhandle)<>Null this.mytype=Object.mytype(savedhandle) ; type handle exists, so we can use it this\A=A this\B=B this\C=C ; then we edit it Else RuntimeError "Type handle specified does not point to any existing one" EndIf End Function Last edited 2010 |
| ||
You can also directly specify the function's type: You could use Object and Handle if you wanted for example to store your type in a Bank. What could be interesting is to look what the value of "handle" is when creating types: Last edited 2010 |
| ||
You can also create an array of type pointers, and use that to access your type list. eg. Type T_mytype Field a# Field b# Field c# End Type Dim mytype_array.T_mytype( 100 ) Global G_mytype.T_mytype ; >>> Create type objects and add their pointers to the array here. G_mytype = mytype_array( 50 ) |
| ||
Hey Bill, that's a good idea. I often find that it gets a little 'tedious' having to Object every Handle I pass to a function after I've just iterated theough the objecvts to obtain that handle. By using the array (Or maybe even, a Type of Type Handles? :D ) it keeps things much more organised! |
| ||
I don't know why Mark didn't just allow the type pointers themselves to be accessed as an integer number - the way he did with entity handles. It would have made Object/Handle redundant, and everyone's life a hell of a lot simpler. Sometimes compiler developers need to just back away from the hand-holding, and let the programmers using their compilers get on with their jobs without tripping over training wheels that they don't need. Last edited 2010 |
| ||
You can pass Types directly to functions as well: |
| ||
I don't know why Mark didn't just allow the type pointers themselves to be accessed as an integer number - the way he did with entity handles. It would have made Object/Handle redundant, and everyone's life a hell of a lot simpler. You can do this with the FastPointer userlib, like so: Type foo Field anInteger End Type Bar.foo=new foo pBar=TypePointer(Bar) My favorite part about this feature is that you can treat the type pointer like a bank using the memory functions provided in the lib (MemoryPokeByte, MemoryPeekByte, etc.) |
| ||
I don't know why Mark didn't just allow the type pointers themselves to be accessed as an integer number - the way he did with entity handles. It would have made Object/Handle redundant, and everyone's life a hell of a lot simpler. Object/Handle is type-safe: if you call Object with a Handle generated from an instance of another type, or a Handle generated from a now-deleted instance, it returns Null rather than a pointer to something inappropriate. Allowing arbitrary conversion from any pointer to an integer would lose this safety. An UnsafeObject/UnsafeHandle command would have been nice for performance, but nightmarish for less advanced users. There's also the issue that in order for the Type List system to work, the variables used in your B3D code are actually double pointers (the first one is dereferenced implicitly when you pass the variable to a DLL or get the pointer via TypePointer, and points to the struct containing the First/Last/Deleted info). Your int is therefore either a pointer to the first struct, which is all very well but a bit annoying to use, or to the object itself, which causes problems if it was deleted, and doesn't give you any obvious way to actually get the "variable pointer" back (maybe it does, I haven't investigated this thoroughly). |