Jump to content

Metin2 Client UI design/create new UI elements


Recommended Posts

  • Premium

Hello,

 

I'm trying to figure out how to create a new button using patterns already created for the buttons in game, but I cannot seem to figure out where the button is actually created, what have i found till now is:

 

In ui.py module there multipe classes  for ui elements, like button, which makes sense to create a instance of that class for the buttons, and i've seen alot of calls to "getChild" method from ScriptWindow class, which just returns what I assume the actual method for the name (key) received from the getChild method call, which is the actual ui element instance

What I cannot figure out where do the ui elements instaces are being set in ElementDictionary in ScriptWindow, searching for the keys from getChild method calls, dosen't return any findings for any "InsertChild" method calls.

Basically, how does this work, do i have to create a button instace based on ui,Button class, then set it intto the dictionary, and then getting it in another method?

 

Thanks

Edited by astroNOT
  • Think 1
  • Love 1
Link to comment
Share on other sites

  • Developer

ScriptWindow (as the name suggests) are window created using scriptfiles (you can find a lot of them in uiscript and in locale/xx/ui).

These script files are (in short) a dictionary of items with settings of certain keys used by PythonScriptLoader class to assign to the elements the properties linked with the keys.

 

Let's show here an example:
 

Spoiler

File uiscript/inputdialog.py

 










import uiScriptLocale

window = {
	"name" : "InputDialog",

	"x" : 0,
	"y" : 0,

	"style" : ("movable", "float",),

	"width" : 170,
	"height" : 90,

	"children" :
	(
		{
			"name" : "Board",
			"type" : "board_with_titlebar",

			"x" : 0,
			"y" : 0,

			"width" : 170,
			"height" : 90,

			"title" : "",

			"children" :
			(

				## Input Slot
				{
					"name" : "InputSlot",
					"type" : "slotbar",

					"x" : 0,
					"y" : 34,
					"width" : 90,
					"height" : 18,
					"horizontal_align" : "center",

					#"type" : "image",
					#"image" : "d:/ymir work/ui/public/Parameter_Slot_03.sub",

					"children" :
					(
						{
							"name" : "InputValue",
							"type" : "editline",

							"x" : 3,
							"y" : 3,

							"width" : 90,
							"height" : 18,

							"input_limit" : 12,
						},
					),
				},

				## Button
				{
					"name" : "AcceptButton",
					"type" : "button",

					"x" : - 61 - 5 + 30,
					"y" : 58,
					"horizontal_align" : "center",

					"text" : uiScriptLocale.OK,

					"default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
					"over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
					"down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
				},
				{
					"name" : "CancelButton",
					"type" : "button",

					"x" : 5 + 30,
					"y" : 58,
					"horizontal_align" : "center",

					"text" : uiScriptLocale.CANCEL,

					"default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
					"over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
					"down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
				},
			),
		},
	),
}

 

 

All the scripts have local variable named window (the dictionary that contains all the settings).

The first dictionary's (window) keys describe the scriptwindow properties, the window name, the height/width, the x/y where the window spawn, the style of the window (in this case moveable mean the window can be moved with the mouse and float mean the window has an order how the children are show and they can be moved over other children using SetTop).

 

the window usually has a "children" key that describe a tuple of dictionaries.

The tuple start with "(" and end with ")," and it contains other dictionaries that describe the children properties.

 

and example is the "Board" child that is a "board_with_titlebar" element (so a board with a titlebar and a close button on the top side).

the "type" key is really important, it describe what kind of element is going to be create. You can read all types available and all keys you can use to assign properties to the elements in the class PythonScriptLoader (especially in def LoadChildren) in ui.py.

 

The self.GetChild you mentioned is used to obtain the element using its "name" property.

The script window are a really clever way to make a window, but it has some limit.

The window made by using the script window can contain in the script only the "static" elements, the elements that are always created with the board.

To create dynamically the elements you have to code them and to assign the properties using the class methods defined in ui.py

An example on how you can create a button would be:
 

import ui
...
...
...

class MyBoardExample(ui.Window):
  ...
  ...
  ...
  ...
  
  
  def LoadDynamicElements(self):
    race = player.GetRace()
    race_image_default = "d:/ymir work/ui/game/race_%d_default.sub"%race
    race_image_down = "d:/ymir work/ui/game/race_%d_down.sub"%race
    race_image_over = "d:/ymir work/ui/game/race_%d_over.sub"%race
    
    self.MainCharRaceButton = ui.Button()
    self.MainCharRaceButton.SetParent(self) #giving the parent to link the button the main board
    self.MainCharRaceButton.SetPosition(105, 456) #giving position using local coordinates
    self.MainCharRaceButton.SetUpVisual(race_image_default) #setting up visual (the image shown when button is in default state)
    self.MainCharRaceButton.SetDownVisual(race_image_down)  #setting down visual (the image show when button is pressed)
    self.MainCharRaceButton.SetOverVisual(race_image_over)	#setting over visual (the image shown when mouse come over the button)
    self.MainCharRaceButton.SAFE_SetEvent(self.__OnClickMainCharRaceButton) #setting an event to the button defined above
    self.MainCharRaceButton.Show() #the show is necessary to see the button
    
    

    
    
    
    

 

 

In the e.g. i created a button that change its visual based on the player character race.

WARNING: the code above wont work since the images and the event are invented and they don't exist

 

Edited by Ikarus_
  • Metin2 Dev 1
  • Love 4

My youtube channel  on which you can see my works here

Link to comment
Share on other sites

  • Premium
32 minutes ago, Ikarus_ said:

ScriptWindow (as the name suggests) are window created using scriptfiles (you can find a lot of them in uiscript and in locale/xx/ui).

These script files are (in short) a dictionary of items with settings of certain keys used by PythonScriptLoader class to assign to the elements the properties linked with the keys.

 

Let's show here an example:
 

  Reveal hidden contents

File uiscript/inputdialog.py

 











import uiScriptLocale

window = {
	"name" : "InputDialog",

	"x" : 0,
	"y" : 0,

	"style" : ("movable", "float",),

	"width" : 170,
	"height" : 90,

	"children" :
	(
		{
			"name" : "Board",
			"type" : "board_with_titlebar",

			"x" : 0,
			"y" : 0,

			"width" : 170,
			"height" : 90,

			"title" : "",

			"children" :
			(

				## Input Slot
				{
					"name" : "InputSlot",
					"type" : "slotbar",

					"x" : 0,
					"y" : 34,
					"width" : 90,
					"height" : 18,
					"horizontal_align" : "center",

					#"type" : "image",
					#"image" : "d:/ymir work/ui/public/Parameter_Slot_03.sub",

					"children" :
					(
						{
							"name" : "InputValue",
							"type" : "editline",

							"x" : 3,
							"y" : 3,

							"width" : 90,
							"height" : 18,

							"input_limit" : 12,
						},
					),
				},

				## Button
				{
					"name" : "AcceptButton",
					"type" : "button",

					"x" : - 61 - 5 + 30,
					"y" : 58,
					"horizontal_align" : "center",

					"text" : uiScriptLocale.OK,

					"default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
					"over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
					"down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
				},
				{
					"name" : "CancelButton",
					"type" : "button",

					"x" : 5 + 30,
					"y" : 58,
					"horizontal_align" : "center",

					"text" : uiScriptLocale.CANCEL,

					"default_image" : "d:/ymir work/ui/public/middle_button_01.sub",
					"over_image" : "d:/ymir work/ui/public/middle_button_02.sub",
					"down_image" : "d:/ymir work/ui/public/middle_button_03.sub",
				},
			),
		},
	),
}

 

 

All the scripts have local variable named window (the dictionary that contains all the settings).

The first dictionary's (window) keys describe the scriptwindow properties, the window name, the height/width, the x/y where the window spawn, the style of the window (in this case moveable mean the window can be moved with the mouse and float mean the window has an order how the children are show and they can be moved over other children using SetTop).

 

the window usually has a "children" key that describe a tuple of dictionaries.

The tuple start with "(" and end with ")," and it contains other dictionaries that describe the children properties.

 

and example is the "Board" child that is a "board_with_titlebar" element (so a board with a titlebar and a close button on the top side).

the "type" key is really important, it describe what kind of element is going to be create. You can read all types available and all keys you can use to assign properties to the elements in the class PythonScriptLoader (especially in def LoadChildren) in ui.py.

 

The self.GetChild you mentioned is used to obtain the element using its "name" property.

The script window are a really clever way to make a window, but it has some limit.

The window made by using the script window can contain in the script only the "static" elements, the elements that are always created with the board.

To create dynamically the elements you have to code them and to assign the properties using the class methods defined in ui.py

An example on how you can create a button would be:
 




import ui
...
...
...

class MyBoardExample(ui.Window):
  ...
  ...
  ...
  ...
  
  
  def LoadDynamicElements(self):
    race = player.GetRace()
    race_image_default = "d:/ymir work/ui/game/race_%d_default.sub"%race
    race_image_down = "d:/ymir work/ui/game/race_%d_down.sub"%race
    race_image_over = "d:/ymir work/ui/game/race_%d_over.sub"%race
    
    self.MainCharRaceButton = ui.Button()
    self.MainCharRaceButton.SetParent(self) #giving the parent to link the button the main board
    self.MainCharRaceButton.SetPosition(105, 456) #giving position using local coordinates
    self.MainCharRaceButton.SetUpVisual(race_image_default) #setting up visual (the image shown when button is in default state)
    self.MainCharRaceButton.SetDownVisual(race_image_down)  #setting down visual (the image show when button is pressed)
    self.MainCharRaceButton.SetOverVisual(race_image_over)	#setting over visual (the image shown when mouse come over the button)
    self.MainCharRaceButton.SAFE_SetEvent(self.__OnClickMainCharRaceButton) #setting an event tu the button defined above
    self.MainCharRaceButton.Show() #the show is necessary to see the button
    
    

    
    
    
    

 

 

In the e.g. i created a button that change its visual based on the player character race.

WARNING: the code above wont work since the images and the event are invented and they don't exist

 

I can only thank you for the explanations, this is quite the insight, which i've legit missed by a mile!

  • Metin2 Dev 1
Link to comment
Share on other sites

  • 2 months later...

Announcements



×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.