Function->Type..?

BlitzMax Forums/BlitzMax Beginners Area/Function->Type..?

Is this not possible?

Function cTextfield( x%, y%, width%, height%, name$)

Local name$:Ttxtbox=New Ttxtbox
name$.x#=x%
name$.x#=y%

i wanted to like do mytxtb = cTextfield(...) but i dont think this is possible either.. or is it?

Teach me ;D

Why are you double-declaring the type of the local variable name. You're putting a string after it, to say it's a string, and then declaring it as a Ttxtbox.

Not really sure what you're trying to do, and your code has a few problems. This should help:
Function cTextfield:tTxtBox( x%, y%, width%, height%, name$)
  Local name:tTxtbox=New tTxtBox
  name.x#=x%
  name.y#=y%
  Return name
End Function

Type tTxtBox
  Field x:float
  Field y:float
End Type


Kaisuo: remember that $ % # etc. are shortcuts from classic BASIC legacy. bla$="w00t!" is the same as bla:string="w00t!". That knowledge should clear-up your name$:Ttxtbox thing, essentially it says name:string:Ttxtbox, which is of course wrong.
Additionally, you only need to add $ % # or any typename upon creation of that instance.

Like:

Local bla$
bla="w00t!"
bla:+" more w00t!"
bla:+bla
notify bla

As you see, you don't need to keep on typing that $ symbol.

remember that $ % # etc. are shortcuts from classic BASIC legacy

I can never remember what they represent (except for $), I much prefer the :String :Int :Float way of doing things, it greatly improves readability.

That's probably because string were the only variables in classic BASIC that were obviously different from the rest. The rest was probably just auto-initialised as single precision orso, usually one didn't care about variable types. -boy did the old days stink ^_^- One just did FOR A=0 TO 255 .. and it worked. 'A' is .. what? Probably some expensive single precision variable. Hence, what ppl remember is $ for text, the rest never was important.

even without this typo, the function is pointless and wrong.

Either you wanted that:

Function cTextfield:tTxtBox( x%, y%, width%, height%)
  Local result:tTxtbox=New tTxtBox
  result.x=x
  result.y=y
  Return result
End Function


which does not take the name as it is not needed.

or you wanted that:
Function cTextfield( x%, y%, width%, height%, var name:tTxtBox)
  name=New tTxtBox
  name.x=x
  name.y=y
End Function



I strongly suggestion to look for assaris tutorials and learn how to use the documentation before proceeding further and trying to get anything done, you sadly lack the pure basics of type declaration which means you won't be able to do anything as this is the total "minimum" knowledge beside basic branching and looping knowledge

I just don't know how to express in english what I'm trying to do. Basicly I was trying to use the name of the text box as the declaring name for the new text box so as such it would not conflic with eachother if I declared more then one... like going like this:
cTextfield(..., name here)
cTextfield(..., name here)
...
I'd think if both of their objects had the same name, then it would work.

Because I'm trying to make an object of the textbox within the function so the function can be re-used. That is why I did the thing above. But that would not work since it's a strign stored in a variable and cannot convert that string to make itself a variable...

if that makes any sense at all...

EDITED
sorry for the late responce... real life -> time consuming ;D

EDITED
I've just re-writen my code. Made it into an object type thingy instead of a fonction, but it takes way too many lines to give it all the info it needs, I'd like it to be only one line like a function.

But I was told not to put new objects in loops.. for I dunno what but I think it'd affect memory.

How would you make this type into a function using the type so I can only type in one line in the loop and also re-use that function?

Graphics 800,600,0

'-------------------------
' VARIABLES
Global gExit:Int = False

'-------------------------
' TYPES
Type cTextfield
	Field x:Int,y:Int 
	Field width:Int,height:Int=15
	Field ftext:String
	Field selected:Int
	
	Method Update()
		If(MouseX()>x)And(MouseX()<(x+width))And(MouseY()>y)And(MouseY()<(y+height))
			SetColor(130,200,240)
		Else
			SetColor(0,170,255)
		EndIf

		DrawLine( x, y, x+width, y) 						' top
		DrawLine( x, y+height, x+width, y+height) 			' bottom
		DrawLine( x, y, x, y+height) 						' left
		DrawLine( x+width, y, x+width, y+height) 			' right
		DrawText( ftext, x+2, y+1 )
	End Method
End Type

test:cTextfield = New cTextfield

'-------------------------
' LOOP
While Not gExit = True
Cls

test.x=100
test.y=100
test.width=100
test.ftext="What?"
test.Update()

'-------------------------
' Close Game
If KeyHit(KEY_ESCAPE) Or AppTerminate() Then 
	gExit = True 
EndIf
'-------------------------
Flip
Wend
End


oh ya ive been reading some of the tuts in the tuts section and i find them to be very enlightning :D

EDITED
I guess the closest thing if not the thing, to what i wanted to do would be:
Function cTextfield( x%, y%, width%, height%, var name:tTxtBox)
  name=New tTxtBox
  name.x=x
  name.y=y
End Function

from dreamora..

UPDATE
This is my current code, I tried to apply dreamora's thing to my own which does not seem to work right now, I could use the help, what is wrong with my current code?
Graphics 800,600,0

'-------------------------
' GVARIABLES
Global gExit:Int = False

'-------------------------
' LOOP
While Not gExit = True
Cls

cTextfield( 10, 10, 100, test:Textfield)

'-------------------------
' Close Game
If KeyHit(KEY_ESCAPE) Or AppTerminate() Then 
	gExit = True 
EndIf
'-------------------------
Flip
Wend
End

'-------------------------
' TYPES
Type Textfield
	Field x:Int,y:Int 
	Field width:Int,height:Int=15
	Field ftext:String
	Field selected:Int
	
	Method Update()
		If(MouseX()>x)And(MouseX()<(x+width))And(MouseY()>y)And(MouseY()<(y+height))
			SetColor(130,200,240)
		Else
			SetColor(0,170,255)
		EndIf

		DrawLine( x, y, x+width, y) 						' top
		DrawLine( x, y+height, x+width, y+height) 			' bottom
		DrawLine( x, y, x, y+height) 						' left
		DrawLine( x+width, y, x+width, y+height) 			' right
		DrawText( ftext, x+2, y+1 )
	End Method
End Type

'-------------------------
' FUNCTIONS
Function cTextfield( x:Int, y:Int, width:Int, Var name:Textfield )
	name=New Textfield
	name.x=x
	name.y=y
	name.width=width
	name.Update()
End Function


it should be:
Function cTextfield( x:Int, y:Int, width:Int, name:Textfield var )


Thanks man it works now.

btw would you or anyone know if there's anything wrong with this?
...
		If(MouseX()>x)And(MouseX()<(x+width))And(MouseY()>y)And(MouseY()<(y+height))
			mover=True
			If(MouseHit(1))Then
				selected=True
			EndIf
		Else
...


I don't know if its the same as B3d, but in B3d MouseHit is only stored once, so you have to flush it like so:

While not Keyhit(1)

Cursorhit1=MouseHit(1)


		If(MouseX()>x)And(MouseX()<(x+width))And(MouseY()>y)And(MouseY()<(y+height))
			mover=True
			If(CursorHit1)Then
				selected=True
			EndIf
		Else
....


?

Repeat
    cTextfield( 10, 10, 100, test:Textfield)

    Flip
    Cls
Until KeyHit(KEY_ESCAPE) Or AppTerminate()
Then you can get rid of that Global variable

planing to add something when the game ends thus why I added the global :)

btw the MouseHit detection isnt working... why isnt it like keyhit :x

i tried
If(KeyHit(MOUSE_LEFT))Then
selected=True
EndIf
it will not work :x
Graphics 800,600,0

'-------------------------
' GVARIABLES
Global gExit:Int = False

'-------------------------
' LOOP
While Not gExit = True
Cls

cTextfield( 10, 10, 100, test1:Textfield)
cTextfield( 10, 70, 100, test2:Textfield)

'-------------------------
' Close Game
If KeyHit(KEY_ESCAPE) Or AppTerminate() Then 
	gExit = True 
EndIf
'-------------------------
Flip
Wend
End

'-------------------------
' TYPES
Type Textfield
	Field x:Int,y:Int 
	Field width:Int,height:Int=15
	Field txt:String
	Field mover:Int=False
	Field selected:Int=False
	
	Method Update()
		
		If(MouseX()>x)And(MouseX()<(x+width))And(MouseY()>y)And(MouseY()<(y+height))
			mover=True
			If(MouseHit(1))
				selected=True
			EndIf
		Else
			mover=False
		EndIf
		
		If(mover=True)Or(selected=True)
			SetColor(0,255,200)
		Else
			SetColor(0,130,130)
		EndIf

		DrawLine( x, y, x+width, y) 						' top
		DrawLine( x, y+height, x+width, y+height) 			' bottom
		DrawLine( x, y, x, y+height) 						' left
		DrawLine( x+width, y, x+width, y+height) 			' right
		DrawText( txt, x+2, y+1 )
	End Method
End Type

'-------------------------
' FUNCTIONS
Function cTextfield( x:Int, y:Int, width:Int, name:Textfield Var )
	name=New Textfield
	name.x=x
	name.y=y
	name.width=width
	name.Update()
End Function


if id think smart i'd say its because the creation of the object is looped so going over the first one and keeping the color the same (name=New Textfield)

try this:

create a global veriable before the main loop like so:


Global Mouseclick1



then in your function before you do the click calls.. do this:


Mouseclick1=Mousehit(1)



Then for your click callings instead of


If(MouseHit(1))



use

If(Mouseclick1)



does that work??

nope, not at all :x

hmm, sorry then, i'm just a B3D noob trying to learn max :D

You're recreating your textfield type each cycle which causes 'Selected' to be reset. You need to create them once before the mainloop, add them to a list and then cycle through the list during your mainloop running update for each.

That sounds like impossible with the current way this is coded. So how exactly am I supposed to do that?
*stupidly confused on how to do this*

Well...
1) Move your the create outside the mainloop.
2) When you create add each object to a list
3) In the mainloop check for mousehit(1), store the coords and check them against each object on the list.
<edit>
Very quick and dirty
SuperStrict
Type textfield
	Global list:tlist=CreateList()
	Field x:Int
	Field y:Int
	Field height:Int
	Field width:Int
	Field red:Int=0
	Field green:Int=0
	Field blue:Int=255
	Field selected:Int=False
	Function Create(x:Int , y:Int , width:Int , height:Int)
		Local TEMP:textfield = New textfield
		temp.x = x
		temp.y = y
		temp.width = width
		temp.height = height
		ListAddLast list , temp
	End Function
	Function Draw()
		For Local all:textfield = EachIn list
			all.Draw_textfield()
		Next
	End Function
	Method Draw_textfield()
		SetColor red,green,blue
		DrawRect x , y , width ,height
	End Method
	Function check(mx:Int , my:Int)
		For Local all:textfield = EachIn list
			all.check_textfield(mx , my)
		Next
	End Function
	Method check_textfield(mx:Int , my:Int)
		If mx > x And mx < x + width And my > y And my < y + height
			Selected = True
			red = 255
			blue=0
		Else
			Selected = False
			red = 0
			blue=255
		EndIf
	End Method
	
End Type
Graphics 800 , 600
create_textfield(100 , 100 , 100 , 40)
create_textfield(100 , 300 , 100 , 40)
While Not KeyHit(KEY_ESCAPE)
	Cls
	Local mh1:Int = MouseHit(1)
	If mh1
		Local mx:Int = MouseX()
		Local my:Int = MouseY()
		check_textfield(mx , my)
	End If
	textfield.Draw
	Flip
Wend
Function create_textfield(x:Int , y:Int , width:Int , height:Int)
	textfield.Create(x , y , width , height)
End Function
Function check_textfield(mx:Int , my:Int)
	textfield.check(mx , my) 
End Function
Function draw_textfield() 
	textfield.Draw
End Function


I somewhat get what you mean. This would mean creating different loops for all the rooms...I wanted everything done by one command so that way it would look cleaner. I'll try to find a way to work this out somehow... Thanks.

Either have a field specifying the 'room or use seperate lists for each room.
Very difficult to suggest the right answer if you don't say what the aim is.
The code I posted is the answer to the question you asked last time.

maybe some timer based on creation like so(b3d but will give ya an idea):


Type made
field times=0
end type

function create(blah,blah,blah)

ticker1.made = new made

if ticker1\times=0

....Create your text field....

ticker1\times=1
end if



@tonyg... the dirty part of your code:

		If mx > x And mx < x + width And my > y And my < y + height


if one just copies this, the first and the last pixel of height and width are not accepted - a >= and <= is needed ;D.

And no, its no "just want to say something" - its posting in beginners area where some users try to copypaste given code to make it work. (so: do not feel offended please)


bye
MB

No offense taken Michael. I think that means I have never checked the last pixel.
@kaisuo, I had another think.
Create a type called TRoom which contains a field called Textfield_list:Tlist and one called RoomName:string When you run Create_textfield pass RoomName as a parm, find the matching TRoom and add the newly created Textfield object to the list for that room.

@tonyg: not a bad idea.
I've been wondering if it works if you have multiple loops in a game as:

//create
while room=1
//do this
wend

//create
while room=2
// do this
wend

or something along those lines :o
Having one command doing all the work is nice but way too much work for my newbieness xD