Difference between revisions of "Crash Course to Hollywood Programming/Example 2 - Hollywood Programming"

From MorphOS Library

< Crash Course to Hollywood Programming

(Created page with "== Hollywood Programming Example == The previous example could be extended to have more commands to be executed in batch, which could be fine for presentations or slideshows,...")
 
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
== Hollywood Programming Example ==
 
== Hollywood Programming Example ==
 +
=== Source Code ===
 +
<nowiki>
 +
@VERSION 6,0
 +
@APPTITLE "Hollywood Example"
 +
@APPVERSION "$VER: Hollywood Example 1.0 (31.10.17)"
 +
@APPDESCRIPTION "A Hollywood example program."
 +
@DISPLAY {Title="Hollywood Example", ScreenTitle="Hollywood Example", Width=400, Height=300, Sizeable=True, Layers=True, ScaleMode=#SCALEMODE_LAYER, SmoothScale=True}
 +
@BRUSH 1, "MOSSYS:Data/Jalapeno/ReadMode.png", {LoadAlpha=True}
  
The previous example could be extended to have more commands to be executed in batch, which could be fine for
+
Function p_DrawGfx()
 +
    Local brush_number = Rnd(2) + 1
 +
    If LayerExists("gfx") Then RemoveLayerFX("gfx")
 +
    SetDisplayAttributes({Title = "Brush " .. brush_number})
 +
    DisplayBrushFX(brush_number, #CENTER, #CENTER)
 +
    SetLayerName(0, "gfx")
 +
EndFunction
 +
 
 +
Function p_Input(msg)
 +
    DebugPrint("Input event!", msg.Action)
 +
    Switch(msg.Action)
 +
    Case "OnKeyDown":
 +
        DebugPrint(msg.Key, "key was pressed.")
 +
        Switch(msg.Key)
 +
        Case " ":
 +
            p_DrawGfx()
 +
        Case "ESC":
 +
            DebugPrint("Quitting...")
 +
            End
 +
        EndSwitch
 +
    Case "OnMouseDown":
 +
        p_DrawGfx()
 +
    EndSwitch
 +
EndFunction
 +
 
 +
LoadBrush(2, "MOSSYS:Data/Jalapeno/TrackMode.png", {LoadAlpha=True})
 +
p_DrawGfx()
 +
 
 +
InstallEventHandler({OnKeyDown = p_Input, OnMouseDown = p_Input})
 +
 
 +
Repeat
 +
  WaitEvent
 +
Forever
 +
</nowiki>
 +
 
 +
=== Description ===
 +
 
 +
The previous example ([[Crash_Course_to_Hollywood_Programming/Example_1_-_The_First_Test|Example 1: The First Test]]) could be extended to have more commands to be executed in batch, which could be fine for
 
presentations or slideshows, but let's take a more practical approach and create an interactive script whose
 
presentations or slideshows, but let's take a more practical approach and create an interactive script whose
 
structure looks like a real program.
 
structure looks like a real program.
  
  
  [http://www.hollywood-mal.com/docs/html/hollywood/atAPPTITLE.html @APPTITLE] "Hollywood Example"
+
  [http://www.hollywood-mal.com/docs/html/hollywood/atVERSION_.html @VERSION] 6,0
  [http://www.hollywood-mal.com/docs/html/hollywood/atAPPVERSION.html @APPVERSION] "$VER: Hollywood Example 1.0 (26.10.17)"
+
 
  [http://www.hollywood-mal.com/docs/html/hollywood/atAPPDESCRIPTION.html @APPDESCRIPTION] "A Hollywood example program."
+
This preprocessor command defines which Hollywood version is required to run the script. If you want to run this example with an earlier version of Hollywood, remove the ScreenTitle attribute from the @DISPLAY preprocessor line.
 +
 
 +
 
 +
[http://www.hollywood-mal.com/docs/html/hollywood/atAPPTITLE_.html @APPTITLE] "Hollywood Example"
 +
  [http://www.hollywood-mal.com/docs/html/hollywood/atAPPVERSION_.html @APPVERSION] "$VER: Hollywood Example 1.0 (26.10.17)"
 +
  [http://www.hollywood-mal.com/docs/html/hollywood/atAPPDESCRIPTION_.html @APPDESCRIPTION] "A Hollywood example program."
  
 
There are several preprocessor commands for adding informative strings to an application. These three are especially
 
There are several preprocessor commands for adding informative strings to an application. These three are especially
Line 17: Line 67:
  
  
  [http://www.hollywood-mal.com/docs/html/hollywood/atDISPLAY.html @DISPLAY] {Title="Hollywood Example", ScreenTitle="Hollywood Example", Width=400, Height=300, Sizeable=True, Layers=True, ScaleMode=#SCALEMODE_LAYER, SmoothScale=True}
+
  [http://www.hollywood-mal.com/docs/html/hollywood/atDISPLAY_.html @DISPLAY] {Title="Hollywood Example", ScreenTitle="Hollywood Example", Width=400, Height=300, Sizeable=True, Layers=True, ScaleMode=#SCALEMODE_LAYER, SmoothScale=True}
  
This time we don't use the [http://www.hollywood-mal.com/docs/html/hollywood/atBGPIC.html @BGPIC] preprocessor, but define the display size manually and add some extra
+
This time we don't use the [http://www.hollywood-mal.com/docs/html/hollywood/atBGPIC_.html @BGPIC] preprocessor, but define the display size manually and add some extra
 
attributes too.
 
attributes too.
  
Line 31: Line 81:
 
The '''Sizeable''' attribute defines if the application window is resizeable by the user.
 
The '''Sizeable''' attribute defines if the application window is resizeable by the user.
  
'''Layers=True''' enables Hollywood's [http://www.hollywood-mal.com/docs/html/hollywood/LayersIntroduction.html layer system]. It depends on the program you're developing whether you want to enable
+
'''Layers=True''' enables Hollywood's [http://www.hollywood-mal.com/docs/html/hollywood/LayersIntroduction_.html layer system]. It depends on the program you're developing whether you want to enable
 
layers or not. With layers enabled all drawing operations get their own layer that can be moved, removed, and
 
layers or not. With layers enabled all drawing operations get their own layer that can be moved, removed, and
 
otherwise processed. When they're disabled, all graphics are just painted over each other on the display and it's
 
otherwise processed. When they're disabled, all graphics are just painted over each other on the display and it's
Line 45: Line 95:
  
  
  [http://www.hollywood-mal.com/docs/html/hollywood/atBRUSH.html @BRUSH] 1, "MOSSYS:Data/Jalapeno/ReadMode.png", {LoadAlpha=True}
+
  [http://www.hollywood-mal.com/docs/html/hollywood/atBRUSH_.html @BRUSH] 1, "MOSSYS:Data/Jalapeno/ReadMode.png", {LoadAlpha=True}
  
 
Brushes are the most common way to load, process, and display graphics in Hollywood. This preprocessor line loads
 
Brushes are the most common way to load, process, and display graphics in Hollywood. This preprocessor line loads
Line 54: Line 104:
  
 
  Function p_DrawGfx()
 
  Function p_DrawGfx()
     [http://www.hollywood-mal.com/docs/html/hollywood/PrgLocals.html Local] brush_number = [http://www.hollywood-mal.com/docs/html/hollywood/Rnd.html Rnd](2) + 1
+
     [http://www.hollywood-mal.com/docs/html/hollywood/PrgLocals_.html Local] brush_number = [http://www.hollywood-mal.com/docs/html/hollywood/Rnd_.html Rnd](2) + 1
     If [http://www.hollywood-mal.com/docs/html/hollywood/LayerExists.html LayerExists]("gfx") Then [http://www.hollywood-mal.com/docs/html/hollywood/RemoveLayerFX.html RemoveLayerFX]("gfx")
+
     If [http://www.hollywood-mal.com/docs/html/hollywood/LayerExists_.html LayerExists]("gfx") Then [http://www.hollywood-mal.com/docs/html/hollywood/RemoveLayerFX_.html RemoveLayerFX]("gfx")
     [http://www.hollywood-mal.com/docs/html/hollywood/SetDisplayAttributes.html SetDisplayAttributes]({Title = "Brush " .. brush_number})
+
     [http://www.hollywood-mal.com/docs/html/hollywood/SetDisplayAttributes_.html SetDisplayAttributes]({Title = "Brush " .. brush_number})
     [http://www.hollywood-mal.com/docs/html/hollywood/DisplayBrushFX.html DisplayBrushFX](brush_number, #CENTER, #CENTER)
+
     [http://www.hollywood-mal.com/docs/html/hollywood/DisplayBrushFX_.html DisplayBrushFX](brush_number, #CENTER, #CENTER)
     [http://www.hollywood-mal.com/docs/html/hollywood/SetLayerName.html SetLayerName](0, "gfx")
+
     [http://www.hollywood-mal.com/docs/html/hollywood/SetLayerName_.html SetLayerName](0, "gfx")
 
  EndFunction
 
  EndFunction
  
This is how you create your own [http://www.hollywood-mal.com/docs/html/hollywood/PrgFunctions.html functions] in Hollywood. Our own function names should always start with the '''p_''' prefix
+
[[File:HollywoodCourse-Example2.png|thumb|Hollywood Example running]]
 +
This is how you create your own [http://www.hollywood-mal.com/docs/html/hollywood/PrgFunctions_.html functions] in Hollywood. Our own function names should always start with the '''p_''' prefix
 
to distinguish them from Hollywood's internal functions. In this case the function doesn't take any parameters and
 
to distinguish them from Hollywood's internal functions. In this case the function doesn't take any parameters and
 
doesn't return any values, it can just be called from the program with p_DrawGfx() to run the lines inside it.
 
doesn't return any values, it can just be called from the program with p_DrawGfx() to run the lines inside it.
  
 
The purpose of this function is to show one of the two brushes we have in memory. The brush ID numbers are 1 and 2, and
 
The purpose of this function is to show one of the two brushes we have in memory. The brush ID numbers are 1 and 2, and
we randomly pick one of them. Because we have the [http://www.hollywood-mal.com/docs/html/hollywood/LayersIntroduction.html layer system] enabled, we get a new layer every time we draw a brush
+
we randomly pick one of them. Because we have the [http://www.hollywood-mal.com/docs/html/hollywood/LayersIntroduction_.html layer system] enabled, we get a new layer every time we draw a brush
 
into the display. To avoid ending up with unlimited number of layers we remove an existing layer first. We also
 
into the display. To avoid ending up with unlimited number of layers we remove an existing layer first. We also
 
change the window title bar text to show the number of the shown brush.
 
change the window title bar text to show the number of the shown brush.
Line 77: Line 128:
  
 
The third line changes the window title text to the brush number we got on the first line. Almost all display attributes
 
The third line changes the window title text to the brush number we got on the first line. Almost all display attributes
can be changed on the fly, and you aren't restricted to the ones you defined with the [http://www.hollywood-mal.com/docs/html/hollywood/atDISPLAY.html @DISPLAY] preprocessor command.
+
can be changed on the fly, and you aren't restricted to the ones you defined with the [http://www.hollywood-mal.com/docs/html/hollywood/atDISPLAY_.html @DISPLAY] preprocessor command.
 
Here you can also see how you can combine a string from other strings or variables with the '''..''' operator, which is
 
Here you can also see how you can combine a string from other strings or variables with the '''..''' operator, which is
 
familiar from Lua.
 
familiar from Lua.
  
[http://www.hollywood-mal.com/docs/html/hollywood/DisplayBrushFX.html DisplayBrushFX]() shows the selected brush and creates a new layer on the layer stack. The position of the brush can be given
+
[http://www.hollywood-mal.com/docs/html/hollywood/DisplayBrushFX_.html DisplayBrushFX]() shows the selected brush and creates a new layer on the layer stack. The position of the brush can be given
in pixels, but also using [http://www.hollywood-mal.com/docs/html/hollywood/PrgInbuiltCst.html inbuilt constants] like '''#CENTER'''. '''FX''' at the end of the function name indicates that there's a
+
in pixels, but also using [http://www.hollywood-mal.com/docs/html/hollywood/PrgInbuiltCst_.html inbuilt constants] like '''#CENTER'''. '''FX''' at the end of the function name indicates that there's a
 
transition effect displayed when the function is called. In most cases they are a bit over the top, and you probably
 
transition effect displayed when the function is called. In most cases they are a bit over the top, and you probably
end up using [http://www.hollywood-mal.com/docs/html/hollywood/DisplayBrush.html DisplayBrush]() or other options to render the graphics.
+
end up using [http://www.hollywood-mal.com/docs/html/hollywood/DisplayBrush_.html DisplayBrush]() or other options to render the graphics.
  
 
Layers get ID numbers automatically and they are assigned dynamically, which means that removing a layer changes the ID
 
Layers get ID numbers automatically and they are assigned dynamically, which means that removing a layer changes the ID
 
numbers of the layers on top of it. To make life easier we can name the layers and handle them by their names
 
numbers of the layers on top of it. To make life easier we can name the layers and handle them by their names
instead of their ID numbers. [http://www.hollywood-mal.com/docs/html/hollywood/SetLayerName.html SetLayerName]() is one way to do that, and we use it to name the layer with the brush here.
+
instead of their ID numbers. [http://www.hollywood-mal.com/docs/html/hollywood/SetLayerName_.html SetLayerName]() is one way to do that, and we use it to name the layer with the brush here.
 
The function accepts a layer ID number and name as parameters. Our displayed brush creates the first layer on the layer
 
The function accepts a layer ID number and name as parameters. Our displayed brush creates the first layer on the layer
stack and its ID number will thus be 1. [http://www.hollywood-mal.com/docs/html/hollywood/SetLayerName.html SetLayerName](1,"gfx") would work in this case, and our layer would get the name "gfx"
+
stack and its ID number will thus be 1. [http://www.hollywood-mal.com/docs/html/hollywood/SetLayerName_.html SetLayerName](1,"gfx") would work in this case, and our layer would get the name "gfx"
 
as intended. But to make life even easier we can give '''ID number 0''' as the first parameter, and the name will be given to the last
 
as intended. But to make life even easier we can give '''ID number 0''' as the first parameter, and the name will be given to the last
 
created layer. This way you don't have to keep count of layers at all.
 
created layer. This way you don't have to keep count of layers at all.
Line 96: Line 147:
  
 
  Function p_Input(msg)
 
  Function p_Input(msg)
     [http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint.html DebugPrint]("Input event!", msg.Action)
+
     [http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint_.html DebugPrint]("Input event!", msg.Action)
 
     Switch(msg.Action)
 
     Switch(msg.Action)
 
     Case "OnKeyDown":
 
     Case "OnKeyDown":
         [http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint.html DebugPrint](msg.Key, "key was pressed.")
+
         [http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint_.html DebugPrint](msg.Key, "key was pressed.")
 
         Switch(msg.Key)
 
         Switch(msg.Key)
 
         Case " ":
 
         Case " ":
 
             p_DrawGfx()
 
             p_DrawGfx()
 
         Case "ESC":
 
         Case "ESC":
             [http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint.html DebugPrint]("Quitting...")
+
             [http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint_.html DebugPrint]("Quitting...")
 
             End
 
             End
 
         EndSwitch
 
         EndSwitch
Line 115: Line 166:
 
message table as their parameter, and we'll get it as a local variable called "msg".
 
message table as their parameter, and we'll get it as a local variable called "msg".
  
[http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint.html DebugPrint]() is a useful function for checking what values we have in certain variables during the program execution. Don't
+
[http://www.hollywood-mal.com/docs/html/hollywood/DebugPrint_.html DebugPrint]() is a useful function for checking what values we have in certain variables during the program execution. Don't
 
hesitate to use it temporarily to learn what results you get from different functions and what values you have in variables.
 
hesitate to use it temporarily to learn what results you get from different functions and what values you have in variables.
 
Here it is used to print the '''Action''' field from the message table, which tells us the name of the event that occured.
 
Here it is used to print the '''Action''' field from the message table, which tells us the name of the event that occured.
  
 
If the user presses a key, we get an '''OnKeyDown''' event, and if the user presses the left mouse button, we get an '''OnMouseDown''' event.
 
If the user presses a key, we get an '''OnKeyDown''' event, and if the user presses the left mouse button, we get an '''OnMouseDown''' event.
A full list of standard events can be found [http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler.html here].
+
A full list of standard events can be found [http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler_.html here].
  
We handle different events with a [http://www.hollywood-mal.com/docs/html/hollywood/PrgSwitch.html Switch-Case] statement in this example, but feel free to handle it in other ways if you please. It
+
We handle different events with a [http://www.hollywood-mal.com/docs/html/hollywood/PrgSwitch_.html Switch-Case] statement in this example, but feel free to handle it in other ways if you please. It
 
is also possible to have a separate function for each event.
 
is also possible to have a separate function for each event.
  
If we take a look at the [http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler.html documentation], we see that the '''OnKeyDown''' event contains the exact key that was pressed in its '''Key'''
+
If we take a look at the [http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler_.html documentation], we see that the '''OnKeyDown''' event contains the exact key that was pressed in its '''Key'''
 
field. It can be accessed with the '''msg.Key''' table item in our function.
 
field. It can be accessed with the '''msg.Key''' table item in our function.
  
The inner [http://www.hollywood-mal.com/docs/html/hollywood/PrgSwitch.html Switch-Case] statement checks if the pressed key was space or escape. If it was '''space''', our previous drawing function
+
The inner [http://www.hollywood-mal.com/docs/html/hollywood/PrgSwitch_.html Switch-Case] statement checks if the pressed key was space or escape. If it was '''space''', our previous drawing function
 
is called and you get new graphics on the display, whereas pressing the '''escape''' key quits the program with a message. Pressing any
 
is called and you get new graphics on the display, whereas pressing the '''escape''' key quits the program with a message. Pressing any
 
other keys will just print the key without doing anything else.
 
other keys will just print the key without doing anything else.
Line 135: Line 186:
  
  
  [http://www.hollywood-mal.com/docs/html/hollywood/LoadBrush.html LoadBrush](2, "MOSSYS:Data/Jalapeno/TrackMode.png", {LoadAlpha=True})
+
  [http://www.hollywood-mal.com/docs/html/hollywood/LoadBrush_.html LoadBrush](2, "MOSSYS:Data/Jalapeno/TrackMode.png", {LoadAlpha=True})
  
The first image in our example program was loaded with the [http://www.hollywood-mal.com/docs/html/hollywood/atBRUSH.html @BRUSH] preprocessor command, but let's load the second image separately.
+
The first image in our example program was loaded with the [http://www.hollywood-mal.com/docs/html/hollywood/atBRUSH_.html @BRUSH] preprocessor command, but let's load the second image separately.
 
The difference between them is that by doing the latter the image doesn't get linked into our executable file when we compile the program. The image
 
The difference between them is that by doing the latter the image doesn't get linked into our executable file when we compile the program. The image
 
is loaded from the filesystem every time you run the program, no matter if it's compiled or not.
 
is loaded from the filesystem every time you run the program, no matter if it's compiled or not.
Line 148: Line 199:
  
  
  [http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler.html InstallEventHandler]({OnKeyDown = p_Input, OnMouseDown = p_Input})
+
  [http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler_.html InstallEventHandler]({OnKeyDown = p_Input, OnMouseDown = p_Input})
  
 
Our previously defined p_Input() function doesn't get any events unless we install event handlers. A table passed to the
 
Our previously defined p_Input() function doesn't get any events unless we install event handlers. A table passed to the
[http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler.html InstallEventHandler]() function defines which events are listened to and what functions they call when triggered. Here
+
[http://www.hollywood-mal.com/docs/html/hollywood/InstallEventHandler_.html InstallEventHandler]() function defines which events are listened to and what functions they call when triggered. Here
 
we define both '''OnKeyDown''' and '''OnMouseDown''' events to call our own '''p_Input()''' function, and user input will work from now on.
 
we define both '''OnKeyDown''' and '''OnMouseDown''' events to call our own '''p_Input()''' function, and user input will work from now on.
 
As you can see, events can call the same function or they can be made to call other functions if necessary.
 
As you can see, events can call the same function or they can be made to call other functions if necessary.
Line 157: Line 208:
  
 
  Repeat
 
  Repeat
     [http://www.hollywood-mal.com/docs/html/hollywood/WaitEvent.html WaitEvent]
+
     [http://www.hollywood-mal.com/docs/html/hollywood/WaitEvent_.html WaitEvent]
 
  Forever  
 
  Forever  
  
This is the main loop of the program. The [http://www.hollywood-mal.com/docs/html/hollywood/WaitEvent.html WaitEvent] function is called repeatedly as long as our program is running and it only
+
This is the main loop of the program. The [http://www.hollywood-mal.com/docs/html/hollywood/WaitEvent_.html WaitEvent] function is called repeatedly as long as our program is running and it only
 
waits for any event to happen. The program just sleeps and doesn't waste any CPU time when there aren't any events.
 
waits for any event to happen. The program just sleeps and doesn't waste any CPU time when there aren't any events.
 +
 +
Save the script as '''hwexample.hws''' and run it with the <code>Hollywood hwexample.hws -quiet</code> command from the shell or with the F4 key in Cubic IDE.
 +
 +
 +
> [[Crash_Course_to_Hollywood_Programming/Example_3_-_System-Friendly_GUI|Proceed to the next example]]

Latest revision as of 07:45, 3 November 2017

Hollywood Programming Example

Source Code

@VERSION 6,0
@APPTITLE "Hollywood Example"
@APPVERSION "$VER: Hollywood Example 1.0 (31.10.17)"
@APPDESCRIPTION "A Hollywood example program."
@DISPLAY {Title="Hollywood Example", ScreenTitle="Hollywood Example", Width=400, Height=300, Sizeable=True, Layers=True, ScaleMode=#SCALEMODE_LAYER, SmoothScale=True}
@BRUSH 1, "MOSSYS:Data/Jalapeno/ReadMode.png", {LoadAlpha=True}

Function p_DrawGfx()
    Local brush_number = Rnd(2) + 1
    If LayerExists("gfx") Then RemoveLayerFX("gfx")
    SetDisplayAttributes({Title = "Brush " .. brush_number})
    DisplayBrushFX(brush_number, #CENTER, #CENTER)
    SetLayerName(0, "gfx")
EndFunction

Function p_Input(msg)
    DebugPrint("Input event!", msg.Action)
    Switch(msg.Action)
    Case "OnKeyDown":
        DebugPrint(msg.Key, "key was pressed.")
        Switch(msg.Key)
        Case " ":
            p_DrawGfx()
        Case "ESC":
            DebugPrint("Quitting...")
            End
        EndSwitch
    Case "OnMouseDown":
        p_DrawGfx()
    EndSwitch
EndFunction

LoadBrush(2, "MOSSYS:Data/Jalapeno/TrackMode.png", {LoadAlpha=True})
p_DrawGfx()

InstallEventHandler({OnKeyDown = p_Input, OnMouseDown = p_Input})

Repeat
   WaitEvent
Forever

Description

The previous example (Example 1: The First Test) could be extended to have more commands to be executed in batch, which could be fine for presentations or slideshows, but let's take a more practical approach and create an interactive script whose structure looks like a real program.


@VERSION 6,0

This preprocessor command defines which Hollywood version is required to run the script. If you want to run this example with an earlier version of Hollywood, remove the ScreenTitle attribute from the @DISPLAY preprocessor line.


@APPTITLE "Hollywood Example"
@APPVERSION "$VER: Hollywood Example 1.0 (26.10.17)"
@APPDESCRIPTION "A Hollywood example program."

There are several preprocessor commands for adding informative strings to an application. These three are especially useful for Amiga and MorphOS programs, because Hollywood programs act like commodities and you'll see this information in, for example, the Exchange program. The @APPVERSION format should respect the standard version string rules, which means that the date should be given in the DD.MM.YY format etc.


@DISPLAY {Title="Hollywood Example", ScreenTitle="Hollywood Example", Width=400, Height=300, Sizeable=True, Layers=True, ScaleMode=#SCALEMODE_LAYER, SmoothScale=True}

This time we don't use the @BGPIC preprocessor, but define the display size manually and add some extra attributes too.

Title defines what will be shown in the window title bar, and ScreenTitle what is shown in the screen title bar when our program window is active.

The Width and Height attributes define the actual drawing area (display) for our application. The application window itself will be a bit larger with the standard OS window borders added around a Hollywood display. It is also possible to open borderless and fullscreen windows without the standard window borders.

The Sizeable attribute defines if the application window is resizeable by the user.

Layers=True enables Hollywood's layer system. It depends on the program you're developing whether you want to enable layers or not. With layers enabled all drawing operations get their own layer that can be moved, removed, and otherwise processed. When they're disabled, all graphics are just painted over each other on the display and it's harder to change or undo things. But if you're just drawing fullscreen graphics to the display or something like that, it's better to keep layers disabled.

ScaleMode sets if display contents are scaled automatically when the display size changes. Many times it's better to keep this disabled and recalculate your own graphics after a resize event to keep the aspect ratio intact and to avoid slowdowns, but let's enable this now to get more functionality into our application without extra lines of code.

SmoothScale makes the scaling output prettier at the expense of speed.


@BRUSH 1, "MOSSYS:Data/Jalapeno/ReadMode.png", {LoadAlpha=True}

Brushes are the most common way to load, process, and display graphics in Hollywood. This preprocessor line loads a PNG image as a brush with ID number 1. All brush handling operations are done by referring to the ID number from now on. The last argument is an optional table containing any extra options for loading. We are using graphics with an alpha channel (transparency) now, so we tell Hollywood to load alpha channel values too.


Function p_DrawGfx()
    Local brush_number = Rnd(2) + 1
    If LayerExists("gfx") Then RemoveLayerFX("gfx")
    SetDisplayAttributes({Title = "Brush " .. brush_number})
    DisplayBrushFX(brush_number, #CENTER, #CENTER)
    SetLayerName(0, "gfx")
EndFunction
Hollywood Example running

This is how you create your own functions in Hollywood. Our own function names should always start with the p_ prefix to distinguish them from Hollywood's internal functions. In this case the function doesn't take any parameters and doesn't return any values, it can just be called from the program with p_DrawGfx() to run the lines inside it.

The purpose of this function is to show one of the two brushes we have in memory. The brush ID numbers are 1 and 2, and we randomly pick one of them. Because we have the layer system enabled, we get a new layer every time we draw a brush into the display. To avoid ending up with unlimited number of layers we remove an existing layer first. We also change the window title bar text to show the number of the shown brush.

The first line of the function declares a new local variable called brush_number and assigns a random value (1 or 2) to it. You should declare new variables as local whenever possible; read more about it here.

The second line checks if we already have a specific layer created, and removes it with a fancy random effect if we do. This line is just skipped when the function is called the first time, because we don't have the specific layer yet.

The third line changes the window title text to the brush number we got on the first line. Almost all display attributes can be changed on the fly, and you aren't restricted to the ones you defined with the @DISPLAY preprocessor command. Here you can also see how you can combine a string from other strings or variables with the .. operator, which is familiar from Lua.

DisplayBrushFX() shows the selected brush and creates a new layer on the layer stack. The position of the brush can be given in pixels, but also using inbuilt constants like #CENTER. FX at the end of the function name indicates that there's a transition effect displayed when the function is called. In most cases they are a bit over the top, and you probably end up using DisplayBrush() or other options to render the graphics.

Layers get ID numbers automatically and they are assigned dynamically, which means that removing a layer changes the ID numbers of the layers on top of it. To make life easier we can name the layers and handle them by their names instead of their ID numbers. SetLayerName() is one way to do that, and we use it to name the layer with the brush here. The function accepts a layer ID number and name as parameters. Our displayed brush creates the first layer on the layer stack and its ID number will thus be 1. SetLayerName(1,"gfx") would work in this case, and our layer would get the name "gfx" as intended. But to make life even easier we can give ID number 0 as the first parameter, and the name will be given to the last created layer. This way you don't have to keep count of layers at all.


Function p_Input(msg)
    DebugPrint("Input event!", msg.Action)
    Switch(msg.Action)
    Case "OnKeyDown":
        DebugPrint(msg.Key, "key was pressed.")
        Switch(msg.Key)
        Case " ":
            p_DrawGfx()
        Case "ESC":
            DebugPrint("Quitting...")
            End
        EndSwitch
    Case "OnMouseDown":
        p_DrawGfx()
    EndSwitch
EndFunction

Here's another function created by us. It is used to handle user input events. Event handling functions will get a message table as their parameter, and we'll get it as a local variable called "msg".

DebugPrint() is a useful function for checking what values we have in certain variables during the program execution. Don't hesitate to use it temporarily to learn what results you get from different functions and what values you have in variables. Here it is used to print the Action field from the message table, which tells us the name of the event that occured.

If the user presses a key, we get an OnKeyDown event, and if the user presses the left mouse button, we get an OnMouseDown event. A full list of standard events can be found here.

We handle different events with a Switch-Case statement in this example, but feel free to handle it in other ways if you please. It is also possible to have a separate function for each event.

If we take a look at the documentation, we see that the OnKeyDown event contains the exact key that was pressed in its Key field. It can be accessed with the msg.Key table item in our function.

The inner Switch-Case statement checks if the pressed key was space or escape. If it was space, our previous drawing function is called and you get new graphics on the display, whereas pressing the escape key quits the program with a message. Pressing any other keys will just print the key without doing anything else.

Pressing the left mouse button also calls our previous drawing function, and the display gets refreshed.


LoadBrush(2, "MOSSYS:Data/Jalapeno/TrackMode.png", {LoadAlpha=True})

The first image in our example program was loaded with the @BRUSH preprocessor command, but let's load the second image separately. The difference between them is that by doing the latter the image doesn't get linked into our executable file when we compile the program. The image is loaded from the filesystem every time you run the program, no matter if it's compiled or not.


p_DrawGfx()

Now that we have both images loaded as brushes, we can call the function we defined earlier, and we get some graphics shown in the application window.


InstallEventHandler({OnKeyDown = p_Input, OnMouseDown = p_Input})

Our previously defined p_Input() function doesn't get any events unless we install event handlers. A table passed to the InstallEventHandler() function defines which events are listened to and what functions they call when triggered. Here we define both OnKeyDown and OnMouseDown events to call our own p_Input() function, and user input will work from now on. As you can see, events can call the same function or they can be made to call other functions if necessary.


Repeat
    WaitEvent
Forever 

This is the main loop of the program. The WaitEvent function is called repeatedly as long as our program is running and it only waits for any event to happen. The program just sleeps and doesn't waste any CPU time when there aren't any events.

Save the script as hwexample.hws and run it with the Hollywood hwexample.hws -quiet command from the shell or with the F4 key in Cubic IDE.


> Proceed to the next example