- Joined
- Jul 18, 2010
- Messages
- 2,377
Introduction
In this tutorial, I wanna show you, Sliders, Checkboxes and attaching Labels to the Sliders and the Checkbox. The sliders are used to control the fields of the cam. The checkbox will lock the current settings, preventing changes to the sliders as long it is checked. And the Labels will show information about the frames they are attached to.
What is a slider?
A slider is a frame for user input. It allows the user to choose a value between an upper and lower limit. You can define for each slider the limits as you please. A Sliders value is local and can differ for all players.
There exist 2 mainFrame Sliders in the default fdf. "EscMenuSliderTemplate" and "StandardSliderTemplate". Both are in fdfs not beeing loaded on default.
There exist 2 mainFrame Sliders in the default fdf. "EscMenuSliderTemplate" and "StandardSliderTemplate". Both are in fdfs not beeing loaded on default.
What is a checkbox?
A checkbox is a frame that toggles between 2 states. The checked and unchecked state. Checking and Unchecking are both own independent events. A checkbox checked state is local and can differ for each player.
What is a Label?
A Label is not a frameType its type is "TEXT", this "TEXT"-frames are used to display text, but also take over space and can throw frameevents when clicking or hovering them with the mouse.
Writing the toc
Cause there is no default loaded mainFrame of type Slider loaded. We first have to create a toc file loading the needed fdf containing the sliders.
We create a new toc-File, named "templates.toc". Its content shall be the text in the next box. Make sure that you add an empty line at the end (on the ptr my tocs failed to load without that empty line).
The toc-files text is not case sensitive.
After you created "templates.toc", wrote its content and saved it. Import the toc-file into your map, keep the path as it is.
Now we need to load the toc file in the maps code, I prefer to know if a toc-Load failed and write an additional function telling me that.
This is the code that will call the custom LoadToc function, which will load the tocFile being placed at "war3mapimported\\templates.toc" (in jass one has to write \\ to have \).
Now that the toc is loaded, we can start creating the sliders. In this tutorial, I use "EscMenuSliderTemplate".
I planed to create 3 sliders, allowing to change cam-distance, cam angle of attack and cam rotation.
We create a new toc-File, named "templates.toc". Its content shall be the text in the next box. Make sure that you add an empty line at the end (on the ptr my tocs failed to load without that empty line).
The toc-files text is not case sensitive.
Code:
UI\FrameDef\Glue\standardtemplates.fdf
UI\FrameDef\UI\escmenutemplates.fdf
UI\FrameDef\Glue\battlenettemplates.fdf
After you created "templates.toc", wrote its content and saved it. Import the toc-file into your map, keep the path as it is.
Now we need to load the toc file in the maps code, I prefer to know if a toc-Load failed and write an additional function telling me that.
JASS:
function LoadToc takes string s returns nothing
if BlzLoadTOCFile(s) then
call BJDebugMsg("Loaded: "+s)
else
call BJDebugMsg("Failed to Load: "+s)
endif
endfunction
This is the code that will call the custom LoadToc function, which will load the tocFile being placed at "war3mapimported\\templates.toc" (in jass one has to write \\ to have \).
call LoadToc("war3mapimported\\templates.toc")
Now that the toc is loaded, we can start creating the sliders. In this tutorial, I use "EscMenuSliderTemplate".
I planed to create 3 sliders, allowing to change cam-distance, cam angle of attack and cam rotation.
Distance Slider + Label
Lets start with 1 slider and its label.
This code creates the slider "distance" and its label.
The sliders parent is the gameUI, but the labels parent is the slider. With the slider beeing the parent of the label, the label shares many actions applied to the slider, like visibility, scale ....
This is a function that will be constantly be executed by a timer. It will frequently read the current chosen value and set the cams distance to that value. It also updates the Labels text so we know the chosen value.
We read the slider by using BlzGetFrameByName using the frames name (EscMenuSliderTemplate) and its create context (0).
Now we create another function which will start the timer doing the updating and call the functions doing the creation and loading.
The result of the current code should look somehow like that.
This code creates the slider "distance" and its label.
The sliders parent is the gameUI, but the labels parent is the slider. With the slider beeing the parent of the label, the label shares many actions applied to the slider, like visibility, scale ....
JASS:
function CreateSliderDistance takes nothing returns nothing
local framehandle fh = BlzCreateFrame("EscMenuSliderTemplate", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 0)
local framehandle label = BlzCreateFrame("EscMenuLabelTextTemplate", fh, 0, 0)
call BlzFrameSetPoint(label, FRAMEPOINT_LEFT, fh, FRAMEPOINT_RIGHT, 0, 0)
call BlzFrameSetAbsPoint(fh, FRAMEPOINT_LEFT, 0.02, 0.5) //below the menu, quest buttons
//call BlzFrameSetSize(fh, 0.139, 0.012) //default size in the fdf.
call BlzFrameSetMinMaxValue(fh, 400, 3000) //limits user can choose; 400 to 3000
call BlzFrameSetValue(fh, 1650) //starting value, should be used after one changed min max
call BlzFrameSetStepSize(fh, 50) //value change from the previous value; how accurate the user can pick values.
endfunction
This is a function that will be constantly be executed by a timer. It will frequently read the current chosen value and set the cams distance to that value. It also updates the Labels text so we know the chosen value.
We read the slider by using BlzGetFrameByName using the frames name (EscMenuSliderTemplate) and its create context (0).
JASS:
function UpdateCam takes nothing returns nothing
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 0)), 0)
call BlzFrameSetText(BlzGetFrameByName("EscMenuLabelTextTemplate", 0), "Distance: " + R2SW(BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 0)), 1, 1))
endfunction
Now we create another function which will start the timer doing the updating and call the functions doing the creation and loading.
JASS:
function CreateCamControll takes nothing returns nothing
call LoadToc("war3mapimported\\templates.toc")
call CreateSliderDistance()
call TimerStart(CreateTimer(), 0.4, true, function UpdateCam)
endfunction

Create other Sliders
Now that the first slider was a success we add 2 further sliders with labels.
The difference between the new sliders and the first slider is the createcontext and changed slider settings. We need to use unique createcontext numbers for frames using the same names to be able to access all of them with BlzGetFrameByName.
Nice now we can change all 3 of them in real time in an ui.

But after having messed around with the settings something stupid like that might happen.

Might be good to add a reset button changing the sliders back to default.
Also it might be good to be able to block changes to the current choosen settings, if one found a good setting and want to protect that against easy missclicks. Lets add a checkbox that can be clicked, when beeing checked the sliders current values can not be changed. Also we add a button that will reset the sliders and with that cam settings.
The difference between the new sliders and the first slider is the createcontext and changed slider settings. We need to use unique createcontext numbers for frames using the same names to be able to access all of them with BlzGetFrameByName.
JASS:
function UpdateCam takes nothing returns nothing
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 0)), 0)
call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 1)), 0)
call SetCameraField(CAMERA_FIELD_ROTATION, BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 2)), 0)
call BlzFrameSetText(BlzGetFrameByName("EscMenuLabelTextTemplate", 0), "Distance: " + R2SW(BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 0)), 1, 1))
call BlzFrameSetText(BlzGetFrameByName("EscMenuLabelTextTemplate", 1), "Angle of Attack: " + R2SW(BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 1)), 1, 1))
call BlzFrameSetText(BlzGetFrameByName("EscMenuLabelTextTemplate", 2), "Rotation: " + R2SW(BlzFrameGetValue(BlzGetFrameByName("EscMenuSliderTemplate", 2)), 1, 1))
endfunction
function CreateSliderAngleOfAttack takes nothing returns nothing
local framehandle fh = BlzCreateFrame("EscMenuSliderTemplate", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 1) //we use CreateContext 1, so the new slider will not overwrite the one saved in slot 0. CreateContext defines the integer the new frame and its children will use in the frame storage. We can read the frame storage with BlzGetFrameByName
local framehandle label = BlzCreateFrame("EscMenuLabelTextTemplate", fh, 0, 1)
call BlzFrameSetPoint(label, FRAMEPOINT_LEFT, fh, FRAMEPOINT_RIGHT, 0, 0)
call BlzFrameSetAbsPoint(fh, FRAMEPOINT_LEFT, 0.02, 0.475) //below the menu, quest buttons
call BlzFrameSetMinMaxValue(fh, 0, 360) //limits user can choose
call BlzFrameSetValue(fh, 304) //startin value
call BlzFrameSetStepSize(fh, 2) //
endfunction
function CreateSliderRotation takes nothing returns nothing
local framehandle fh = BlzCreateFrame("EscMenuSliderTemplate", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 2) //CreateContext 2
local framehandle label = BlzCreateFrame("EscMenuLabelTextTemplate", fh, 0, 2)
call BlzFrameSetPoint(label, FRAMEPOINT_LEFT, fh, FRAMEPOINT_RIGHT, 0, 0)
call BlzFrameSetAbsPoint(fh, FRAMEPOINT_LEFT, 0.02, 0.45) //below the menu, quest buttons
call BlzFrameSetMinMaxValue(fh, 0, 360) //limits user can choose
call BlzFrameSetValue(fh, 90) //startin value
call BlzFrameSetStepSize(fh, 5) //
endfunction
function CreateCamControl takes nothing returns nothing
call LoadToc("war3mapimported\\templates.toc") //use the custom function to load the Toc, the custom function prints success/fail loading the toc.
call CreateSliderAngleOfAttack()
call CreateSliderRotation()
call CreateSliderDistance()
call TimerStart(CreateTimer(), 0.4, true, function UpdateCam)
endfunction

But after having messed around with the settings something stupid like that might happen.

Might be good to add a reset button changing the sliders back to default.
Also it might be good to be able to block changes to the current choosen settings, if one found a good setting and want to protect that against easy missclicks. Lets add a checkbox that can be clicked, when beeing checked the sliders current values can not be changed. Also we add a button that will reset the sliders and with that cam settings.
Checkbox and Reset
Creating the CheckBox locking the sliders.
The code handling the resetbutton, its a function that is executed when the button is pressed and a function creating the button.
We also need to update the create function CreateCamControl.
Now the created frames should look like that.


The framedefinition wouldn't be needed for that tutorial, but now you don't have to search it, if you wana look on the slider definition.
The 3 attached Maps are the different states of the tutorial.
CamSlider1 is after the first slider was created.
CamSlider2 is after all 3 sliders were created.
CamSlider3 has 3 sliders the reset and the Sliderlock.
JASS:
//The function beeing executed when the checkbox is checked/UnChecked.
function CheckBoxLockSliders takes nothing returns nothing
local boolean enable = (BlzGetTriggerFrameEvent() == FRAMEEVENT_CHECKBOX_UNCHECKED) //calc the new state,
if GetLocalPlayer() == GetTriggerPlayer() then //only do stuff for local player
call BlzFrameSetEnable(BlzGetFrameByName("EscMenuSliderTemplate", 0), enable)
call BlzFrameSetEnable(BlzGetFrameByName("EscMenuSliderTemplate", 1), enable)
call BlzFrameSetEnable(BlzGetFrameByName("EscMenuSliderTemplate", 2), enable)
endif
endfunction
function CreateCheckbox takes nothing returns nothing
local trigger trig = CreateTrigger()
local framehandle fh = BlzCreateFrame("QuestCheckBox", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 3) //CreateContext 3 would not be needed for the checkbox cause it uses different names, but we want to use the same labelFrame Type.
local framehandle label = BlzCreateFrame("EscMenuLabelTextTemplate", fh, 0, 3)
call BlzFrameSetPoint(label, FRAMEPOINT_LEFT, fh, FRAMEPOINT_RIGHT, 0, 0)
call BlzFrameSetAbsPoint(fh, FRAMEPOINT_LEFT, 0.15, 0.40)
call BlzFrameSetText(label, "Lock Sliders")
call TriggerAddAction(trig, function CheckBoxLockSliders)
call BlzTriggerRegisterFrameEvent(trig, fh, FRAMEEVENT_CHECKBOX_CHECKED) //execute function when checking the box
call BlzTriggerRegisterFrameEvent(trig, fh, FRAMEEVENT_CHECKBOX_UNCHECKED) //executed when unchecking
endfunction
The code handling the resetbutton, its a function that is executed when the button is pressed and a function creating the button.
JASS:
function ResetSliders takes nothing returns nothing
if GetLocalPlayer() == GetTriggerPlayer() then
call BlzFrameSetValue(BlzGetFrameByName("EscMenuSliderTemplate", 0), 1650)
call BlzFrameSetValue(BlzGetFrameByName("EscMenuSliderTemplate", 1), 304)
call BlzFrameSetValue(BlzGetFrameByName("EscMenuSliderTemplate", 2), 90)
endif
call BlzFrameSetEnable(BlzGetTriggerFrame(), false)//this button loses focus
call BlzFrameSetEnable(BlzGetTriggerFrame(), true)
endfunction
function CreateResetButton takes nothing returns nothing
local trigger trig = CreateTrigger()
local framehandle fh = BlzCreateFrame("ScriptDialogButton", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0, 0) //CreateContext 0, we can reuse it cause it has unique names compread to the sliders and labels.
call BlzFrameSetSize(fh, 0.09, 0.024) //default size is to big
call BlzFrameSetAbsPoint(fh, FRAMEPOINT_RIGHT, 0.15, 0.40)
call BlzFrameSetText(fh, "Reset Cam")
call TriggerAddAction(trig, function ResetSliders)
call BlzTriggerRegisterFrameEvent(trig, fh, FRAMEEVENT_CONTROL_CLICK)
endfunction
We also need to update the create function CreateCamControl.
JASS:
function CreateCamControl takes nothing returns nothing
call LoadToc("war3mapimported\\templates.toc") //use the custom function to load the Toc, the custom function prints success/fail loading the toc.
call CreateSliderAngleOfAttack()
call CreateSliderRotation()
call CreateSliderDistance()
call CreateCheckbox()
call CreateResetButton()
call TimerStart(CreateTimer(), 0.4, true, function UpdateCam)
endfunction


The framedefinition wouldn't be needed for that tutorial, but now you don't have to search it, if you wana look on the slider definition.
Code:
Frame "SLIDER" "EscMenuSliderTemplate" {
Height 0.012,
Width 0.139,
SliderLayoutHorizontal,
ControlBackdrop "EscMenuScrollBarBackdropTemplate",
Frame "BACKDROP" "EscMenuScrollBarBackdropTemplate" {
DecorateFileNames,
BackdropTileBackground,
BackdropBackground "EscMenuSliderBackground",
BackdropCornerFlags "UL|UR|BL|BR|T|L|B|R",
BackdropCornerSize 0.006,
BackdropBackgroundSize 0.006,
BackdropBackgroundInsets 0.0025 0.0025 0.0025 0.0025,
BackdropEdgeFile "EscMenuSliderBorder",
BackdropBlendAll,
}
ControlDisabledBackdrop "EscMenuScrollBarDisabledBackdrop",
Frame "BACKDROP" "EscMenuScrollBarDisabledBackdrop" {
DecorateFileNames,
BackdropTileBackground,
BackdropBackground "EscMenuSliderBackground",
BackdropCornerFlags "UL|UR|BL|BR|T|L|B|R",
BackdropCornerSize 0.006,
BackdropBackgroundSize 0.006,
BackdropBackgroundInsets 0.0025 0.0025 0.0025 0.0025,
BackdropEdgeFile "EscMenuSliderDisabledBorder",
BackdropBlendAll,
}
SliderThumbButtonFrame "EscMenuThumbButtonTemplate",
Frame "BUTTON" "EscMenuThumbButtonTemplate" {
Width 0.016,
Height 0.016,
ControlBackdrop "EscMenuThumbButtonBackdropTemplate",
Frame "BACKDROP" "EscMenuThumbButtonBackdropTemplate" {
DecorateFileNames,
BackdropBlendAll,
BackdropBackground "EscMenuSliderThumbButton",
}
ControlDisabledBackdrop "EscMenuThumbButtonDisabledBackdrop",
Frame "BACKDROP" "EscMenuThumbButtonDisabledBackdrop" {
DecorateFileNames,
BackdropBlendAll,
BackdropBackground "EscMenuSliderDisabledThumbButton",
}
}
}
Code:
Frame "TEXT" "EscMenuLabelTextTemplate" {
DecorateFileNames,
FrameFont "EscMenuTextFont", 0.011, "",
FontJustificationH JUSTIFYLEFT,
FontJustificationV JUSTIFYMIDDLE,
FontFlags "FIXEDSIZE",
FontColor 0.99 0.827 0.0705 1.0,
FontHighlightColor 1.0 1.0 1.0 1.0,
FontDisabledColor 0.2 0.2 0.2 1.0,
FontShadowColor 0.0 0.0 0.0 0.9,
FontShadowOffset 0.002 -0.002,
}
The 3 attached Maps are the different states of the tutorial.
CamSlider1 is after the first slider was created.
CamSlider2 is after all 3 sliders were created.
CamSlider3 has 3 sliders the reset and the Sliderlock.
Other UI-Frame Tutorials
The following links might provide more insight into this subject.
UI: Change Lumber Text
[JASS/AI] - UI: Create a TextButton
[JASS/AI] - UI: Positionate Frames (important)
UI: toc-Files
UI: Reading a FDF
UI - The concept of Parent-Frames
[JASS/AI] - UI: FrameEvents and FrameTypes
UI: Frames and Tooltips
[JASS/AI] - UI: Creating a Bar
UI - Simpleframes
UI: What are BACKDROPs?
UI: GLUEBUTTON
UI: TEXTAREA the scrolling Text Frame
UI: EditBox - Text Input
[JASS/AI] - UI: Creating a Cam control
UI: Showing 3 Multiboards
UI: OriginFrames
Default Names for BlzGetFrameByName (Access to Existing game-Frames)
[JASS/AI] - UI: List - Default MainFrames (built in CreateAble)
UI: Change Lumber Text
[JASS/AI] - UI: Create a TextButton
[JASS/AI] - UI: Positionate Frames (important)
UI: toc-Files
UI: Reading a FDF
UI - The concept of Parent-Frames
[JASS/AI] - UI: FrameEvents and FrameTypes
UI: Frames and Tooltips
[JASS/AI] - UI: Creating a Bar
UI - Simpleframes
UI: What are BACKDROPs?
UI: GLUEBUTTON
UI: TEXTAREA the scrolling Text Frame
UI: EditBox - Text Input
[JASS/AI] - UI: Creating a Cam control
UI: Showing 3 Multiboards
UI: OriginFrames
Default Names for BlzGetFrameByName (Access to Existing game-Frames)
[JASS/AI] - UI: List - Default MainFrames (built in CreateAble)
Attachments
Last edited by a moderator: