Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-google-earth-google-maps-and-your-photos-tutorial
Packt
22 Oct 2009
38 min read
Save for later

Google Earth, Google Maps and Your Photos: a Tutorial

Packt
22 Oct 2009
38 min read
Introduction A scholar who never travels but stays at home is not worthy to be accounted a scholar. From my youth on I had the ambition to travel, but could not afford to wander over the three hundred counties of Korea, much less the whole world. So, carrying out an ancient practise, I drew a geographical atlas. And while gazing at it for long stretches at a time I feel as though I was carrying out my ambition . . . Morning and evening while bending over my small study table, I meditate on it and play with it and there in one vast panorama are the districts, the prefectures and the four seas, and endless stretches of thousands of miles. WON HAK-SAENG Korean Student Preface to his untitled manuscript atlas of China during the Ming Dynasty, dated 1721. To say that maps are important is an understatement almost as big as the world itself. Maps quite literally connect us to the world in which we all live, and by extension, they link us to one another. The oldest preserved maps date back nearly 4500 years. In addition to connecting us to our past, they chart much of human progress and expose the relationships among people through time. Unfortunately, as a work of humankind, maps share many of the same shortcomings of all human endeavors. They are to some degree inaccurate and they reflect the bias of the map maker. Advancements in technology help to address the former issue, and offer us the opportunity to resist the latter. To the extent that it's possible for all of us to participate in the map making, the bias of a select few becomes less meaningful. Google Earth  and Google Maps  are two applications that allow each of us to assert our own place in the world and contribute our own unique perspective. I can think of no better way to accomplish this than by combining maps and photography. Photos reveal much about who we are, the places we have been, the people with whom we have shared those experiences, and the significant events in our lives. Pinning our photos to a map allows us to see them in their proper geographic context, a valuable way to explore and share them with friends and family. Photos can reveal the true character of a place, and afford others the opportunity to experience these destinations, perhaps faraway and unreachable for some of us, from the perspective of someone who has actually been there. In this tutorial I'll show you how to 'pin' your photos using Google Earth and Google Maps. Both applications are free, and available for Windows, Mac OS X, and Linux. In the case of Google Earth there are requirements associated with installing and running what is a local application. Google Maps has its own requirements: primary among them a compatible web browser (the highly regarded FireFox is recommended). In Google Earth, your photos show up on the map within the application complete with titles, descriptions, and other relevant information. You can choose to share your photos with everyone, only people you know, or even reserve them strictly for yourself. Google Maps offers the flexibility to present maps outside of a traditional application. For example you can embed a map on a webpage pinpointing the location of one particular photo, or mapping a collection of photos to present along with a photo gallery, or even collecting all of your digital photos together on one dynamic map. Over the course of a short couple of articles we'll cover everything you need to take advantage of both applications. I've put together two scripts to help us accomplish that goal. The first is a Perl script that works through your photos and generates a file in the proper format with all of the data necessary to include those photos in Google Earth. The second is a short bit of Javascript that works with the first file and builds a dynamic Google Map of those same photos. Both scripts are available for you to download, after which you are free to use them as is, or modify them to suit your own projects. I've purposefully kept the code as simple as possible to make them accessible to the widest audience, even those of you reading this who may be new to programming or unfamiliar with Perl, Javascript or both. I've taken care to comment the code generously so that everything is plainly obvious. I'm hopeful that you will be surprised at just how simple it is. There a couple of preliminary topics to examine briefly before we go any further. In the preceding paragraph I mentioned that the result of the first of our two scripts is a 'file in the proper format...'. This file, or more to the point the file format, is a very important part of the project. KML  (Keyhole Markup Language) is a fairly simple XML-based format that can be considered the native "language" of Google Earth. That description begs the question, 'What is XML?'. To oversimplify, because even a cursory discussion of XML is outside of the scope of this article, XML  (Extensible Markup Language) is an open data format (in contrast to proprietary formats) which allows us to present information in such way that we communicate not only the data itself, but also descriptive information about the data and the relationships among elements of the data. One of the technical terms that applies is 'metalanguage', which approximately translates to mean a language that makes it possible to describe other languages. If you're unfamiliar with the concept, it may be difficult to grasp at first or it may not seem impressive. However, metalanguages, and specifically XML, are an important innovation (I don't mean to suggest that it's a new concept. In fact XML has roots that are quite old, relative to the brief history of computing). These metalanguages make it possible for us to imbue data with meaning such that software can make use of that data. Let's look at an example taken from the Wikipedia entry for KML. <?xml version="1.0" encoding="UTF-8"?> <kml > <Placemark>  <description>New York City</description>  <name>New York City</name>  <Point>  <coordinates>-74.006393,40.714172,0</coordinates>  </Point> </Placemark> </kml>   Ignore all of the pro forma stuff before and after the <Placemark> tags and you might be able to guess what this bit of data represents. More importantly, a computer can be made to understand what it represents in some sense. Without the tags and structure, "New York City" is just a string, i.e. a sequence of characters. Considering the tags we can see that we're dealing with a place, (a Placemark), and that "New York City" is the name of this place (and in this example also its description). With all of this formal structure, programs can be made to roughly understand the concept of a Placemark, which is a useful thing for a mapping application. Let's think about this for a moment. There are a very large number of recognizable places on the planet, and a provably infinite number of strings. Given a block of text, how could a computer be made to identify a place from, for example the scientific name of a particular flower, or a person's name? It would be extremely difficult. We could try to create a database of every recognizable place and have the program check the database every time it encounters a string. That assumes it's possible to agree on a 'complete list of every place', which is almost certainly untrue. Keep in mind that we could be talking about informal places that are significant only to a small number of people or even a single person, e.g. 'the park where, as a child, I first learned to fly a kite'. It would be a very long list if we were going to include these sorts of places, and incredibly time-consuming to search. Relying on the structure of the fragment above, we can easily write a program that can identify 'New York City' as the name of a place, or for that matter 'The park where I first learned to fly a kite'. In fact, I could write a program that pulls all of the place names from a file like this, along with a description, and a pair of coordinate points for each, and includes them on a map. That's exactly what we're going to do. KML makes it possible. If I haven't made it clear, the structural bits of the file must be standardized. KML supports a limited set of elements (e.g. 'Placemark' is a supported element, as are 'Point' and 'coordinates'), and all of the elements used in a file must adhere to the standard for it to be considered valid. The second point we need to address before we begin is, appropriately enough... where to begin? Lewis Carroll famously tells us to "Begin at the beginning and go on till you come to the end: then stop."  Of course, Mr. Carroll  was writing a book at the time. If "Alice's Adventures in Wonderland" were an article, he might have had different advice. From the beginning to the end there is a lot of ground to cover. We're going to start somewhere further along, and make up the difference with the following assumptions. For the purposes of this discussion, I am going to assume that you have: Perl Access to Phil Harvey's excellent ExifTool , a Perl library and command-line application for reading, writing, and editing metadata in images (among other file types). We will be using this library in our first script A publicly accessible web server. Google requires the use of an API key  by which it can monitor the use of its map services. Google must be able to validate your key, and so your site must be publicly available. Note that this a requirement for Google Maps only Photos, preferably in a photo management application. Essentially, all you need is an app capable of generating both thumbnails and reduced size copies of your original photos . An app that can export a nice gallery for use on the web is even better Coordinate data as part of the EXIF metadata  embedded in your photos. If that sounds unfamiliar to you, then most likely you will have to take some additional steps before you can make use of this tutorial. I'm not aware of any digital cameras that automatically include this information at the time the photo is created. There are devices that can be used in combination with digital cameras, and there are a number of ways that you can 'tag' your photos with geographic data much the same way you would add keywords and other annotations. Let's begin!   Part 1: Google Earth Section 1: Introduction to Part 1 Time to begin the project in earnest. As I've already mentioned we'll spend the first half of this tutorial looking at Google Earth and putting together a Perl script whichthat, given a collection of geotagged photos, will build a set of KML files so that we can browse our photos in Google Earth. These same files will serve as the data source for our Google Maps application later on. Section 2: Some Advice Before We Begin Take your time to make sure you understand each topic before you move on to the next. Think of this as the first step in debugging your completed code. If you go slowly enough that you are to be able to identify aspects of the project that you don't quite understand, then you'll have some idea where to start looking for problems should things not go as expected. Furthermore, going slowly will give you the opportunity to identify those parts that you may want to modify to better fit the script to your own needs. If this is new to you, follow along as faithfully as possible with what I do here the first time through. Feel free to make notes for yourself as you go, but making changes on the first pass may make it difficult for you to catch back on to the narrative and piece together a functional script. After you have a working solution, it will be a simple matter to implement changes one at a time until you have something that works for you. Following this approach it will be easy to identify the silly mistakes that tend to creep in once you start making changes. There is also the issue of trust. This is probably the first time we're meeting each other, in which case you should have some doubt that my code works properly to begin with. If you minimize the number of changes you make, you can confirm that this works for you before blaming yourself or your changes for my mistakes. I will tell you up front that I'm building this project myself as we go. You can be certain at least that it functions as described for me as of the date attached to the article. I realize that this is quite different from being certain that the project will work for you, but at least it's something. The entirety of my project is available for you to download. You are free to use all of it for any legal purpose whatsoever,  including my photos in addition to all of the code, icons, etc. This is so you have some samples to use before you involve your own content. I don't promise that they are the most beautiful images you have ever seen, but they are all decent photos and properly annotated with the necessary metadata, including geographic tags. Section 3: Photos, Metadata and ExifTool To begin, we must have a clear understanding of what the Perl script will require from us. Essentially, we need to provide it with a selection of annotated image files, and information about how to reference those files. A simple folder of files is sufficient, and will be convenient for us, both as the programmer and end user. The script will be capable of negotiating nested folders, and if a directory contains both images and other file types, non-image types will be ignored. Typically, after a day of taking photos I'll have 100 to 200 that I want to keep. I delete the rest immediately after offloading them from the camera. For the files that are left, I preserve the original grouping, keeping all of the files together in a single folder. I place this folder of images in an appropriate location according to a scheme that serves to keep my complete collection of photos neatly organized. These are my digital 'negatives'. I handle all subsequent organization, editing, enhancements, and annotations within my photo management application. I use Apple Inc.'s Aperture; but there are many others that do the job equally well. Annotating your photos is well worth the investment of time and effort, but it's important that you have some strategy in mind so that you don't create meaningless tags that are difficult to use to your advantage. For the purposes of this project the tags we'll need are quite limited, which means that going forward we will be able to continue adding photos to our maps with a reasonable amount of work. The annotations we need are: Caption Latitude Longitude Image Date * Location/Sub-Location City Province/State Country Name Event People ImageWidth * ImageHeight * * Values for these Exif tags are generated by your camera. Note that these are labels used in Aperture, and are not necessarily consistent from one application to the next. Some of them are more likely than others to be used reliably. 'City' for example should be dependable, while the labels 'People', 'Events', and 'Location', among others, are more likely to differ. One explanation for these variations is that the meaning of these fields are more open to interpretation. Location, for example, is likely to be used to narrow down the area where the photo was taken within a particular city, but it is left to the person who is annotating the photo to decide that the field should name a specific street address, an informal place (e.g. 'home' or 'school'), or a larger area, for example a district or neighborhood. Fortunately things aren't so arbitrary as they seem. Each of these fields corresponds to a specific tag name that adheres to one of the common metadata formats (Exif1, IPTC2, XMP3, and there are others). These tag names are consistent as required by the standards. The trick is in determining the labels used in your application that correspond to the well-defined tag names. Our script relies on these metadata tags, so it is important that you know which fields to use in your application. This gives us an excuse to get acquainted with ExifTool4. From the project's website, we have this description of the application: ExifTool is a platform-independent Perl library plus a command-line application for reading, writing, and editing meta information in image, audio, and video files... ExifTool can seem a little intimidating at first. Just keep in mind that we will need to understand just a small part of it for this project, and then be happy that such a useful and flexible tool is freely available for you to use. The brief description above states in part that ExifTool is a Perl library and command line application that we can use to extract metadata from image files. With a single short command, we can have the app print all of the metadata contained in one of our image files. First, make sure ExifTool is installed. You can test for this by typing the name of the application at the command line. $ exiftool If it is installed, then running it with no options should prompt the tool to print its documentation. If this works, there will be more than one screen of text. You can page through it by pressing the spacebar. Press the 'q' key at any time to stop. If the tool is not installed, you will need to add it before continuing. See the appendix at the end of this tutorial for more information. Having confirmed that ExifTool is installed, typing the following command will result in a listing of the metadata for the named image: $ exiftool -f -s -g2 /path/image.jpg Where 'path' is an absolute path to image.jpg or a relative path from the current directory, and 'image.jpg' is the name of one of your tagged image files. We'll have more to say about ExifTool later, but because I believe that no tutorial should ask the reader to blindly enter commands as if they were magic incantations, I'll briefly describe each of the options used in the command above: -f, forces printing of tags even if their values are not found. This gives us a better idea about all of the available tag names, whether or not there are currently defined values for those tags. -s, prints tag names instead of descriptions. This is important for our purposes. We need to know the tag names so that we can request them in our Perl code. Descriptions, which are expanded, more human-readable forms of the same names obscure details we need. For example, compare the tag name 'GPSLatitude' to the description 'GPS Latitude'. We can use the tag name, but not the description to extract the latitude value from our files. -g2, organizes output by category. All location specific information is grouped together, as is all information related to the camera, date and time tags, etc.  You may feel, as I do, that this grouping makes it easier to examine the output. Also, this organization is more likely to reflect the grouping of field names used by your photo management application. If you prefer to save the output to a file, you can add ExifTool's -w option with a file extension. $ exiftool -f -s -g2 -w txt path/image.jpg This command will produce the same result but write the output to the file 'image.txt' in the current directory; again, where 'image.jpg' is the name of the image file. The -w option appends the named extension to the image file's basename, creates a new file with that name, and sets the new file as the destination for output. The tag names that correspond to the list of Aperture fields presented above are: metadata tag name Aperture field label Caption-Abstract Caption GPSLatitude Latitude GPSLongitude Longitude DateTimeOriginal Image Date Sub-location Location/Sub-Location City City Province-State Province/State Country-PrimaryLocationName Country Name FixtureIdentifier Event Contact People ImageWidth Pixel Width ImageHeight Pixel Height     Section 4: Making Photos Available to Google Earth We will use some of the metadata tags from our image files to locate our photos on the map (e.g. GPSLatitude, GPSLongitude), and others to describe the photos. For example, we will include the value of the People tag in the information window that accompanies each marker to identify friends and family who appear in the associated photo. Because we want to display and link to photos on the map, not just indicate their position, we need to include references to the location of our image files on a publicly accessible web server. You have some choice about how to do this, but for the implementation described here we will (1) Display a thumbnail in the info window of each map marker and (2) include a link to the details page for the image in a gallery created in our photo management app. When a visitor clicks on a map marker they will see a thumbnail photo along with other brief descriptive information. Clicking a link included as part of the description will open the viewer's web browser to a page displaying a large size image and additional details. Furthermore, because the page is part of a gallery, viewers can jump to an index page and step forward and back through the complete collection. This is a complementary way to browse our photos. Taking this one step further, we could add a comments section to the gallery pages or replace the gallery altogether, instead choosing to display each photo as a weblog post for example. The structure of the gallery created from my photo app is as follows... / (the root of the gallery directory) index.html large-1.html large-2.html large-3.html ... large-n.html assets/ css/ img/ catalog/ pictures/ picture-1.jpg picture-2.jpg picture-3.jpg ... picture-n.jpg thumbnails/ thumb-1.jpg thumb-2.jpg thumb-3.jpg ... thumb-n.jpg The application creates a root directory containing the complete gallery. Assuming we do not want to make any manual changes to the finished site, publishing is as easy as copying the entire directory to a location within the web server's document root. assets/: Is a subfolder containing files related to the theme itself. We don't need to concern ourselves with this sub-directory. catalog/: Contains a single catalog.plist file which is specific to Aperture and not relevant to this discussion. pictures/: Contains the large size images included on the detail gallery pages. thumbnails/: This subfolder contains the thumbnail images corresponding to the large size images in pictures/. Finally, there are a number of files at the root of the gallery. These include index pages and files named 'large-n.html', where n is a number starting at 1 and increasing sequentially e.g. large-1.html, large-2.html, large-3.html, ... The index files are the index pages of our gallery. The number of index pages generated will be dictated by the number of image files in the gallery, as well as the gallery's layout and design. index.html is always the first gallery page. The large-n.html files are the details pages of our gallery. Each page features an individual photo with links to the previous and next photos in sequence and a link back to the index. You can see the gallery I have created for this tutorial here: http://robreed.net/photos/tutorial_gallery/ If you take the time to look through the gallery, maybe you can appreciate the value of viewing these photos on a map. Web-based photo galleries like this one are nice enough, but the photos are more interesting when viewed in some meaningful context. There are a couple of things to notice about this gallery. Firstly, picture-1.jpg, thumb-1.jpg, and large-1.html all refer to the same image. So if we pick one of the three files we can easily predict the names of the other two. This relationship will be useful when it comes to writing our script. There is another important issue I need to call to your attention because it will not be apparent from looking only at the gallery structure. Aperture has renamed all of my photos in the process of exporting them. The name of the original file from which picture-1.jpg was generated (as well as large-1.html and thumb-1.jpg) is 'IMG_0277.JPG', which is the filename produced by my camera. Because I want to link to these gallery files, not my original photos which will stay safely tucked away on a local drive, I must run the script against the photos in the gallery. I cannot run it against the original image files because the filenames referenced in the output are unrelated to the files in the gallery. If my photo management app provided me the option of preserving the original filenames for the corresponding photos in the gallery, then I could run the script against the original image files or the gallery photos because all of the filenames would be consistent, but this is not the case. I don't have a problem as long as I run the script on the exported photos. However, if I'm running the script against the photos in the web gallery, either the pictures or thumbnail images must contain the same metadata as the original image files. Aperture preserves the metadata in both. Your application may not. A simple, dependable way to confirm that the metadata is present in the gallery files is to run ExifTool first against the original file and then the same photo in the pictures/ and thumbnails/ directories in the gallery. If ExifTool reports identical metadata, then you will have no trouble using one of pictures/ or thumbnails/ as your source directory. If the metadata is not present or not complete in the gallery files, you may need to use the script on your original image files. As has already been explained, this isn't a problem unless the gallery produces filenames that are inconsistent with the original filenames, as Aperture does. In this case you have a problem. You won't be able to run the script on the original image files because of the naming issue or on the gallery photos because they don't contain metadata. Make sure that you understand this point. If you find yourself in this situation, then your best bet is to generate files to use with your maps from your original photos in some other way, bypassing your photo management app's web gallery features altogether in favor of a solution that preserves the filenames, the metadata, or both. There is another option which involves setting up a relationship between the names of the original files and the gallery filenames. This tutorial does not include details about how to set up this association. Finally, keep in mind that though we've looked at the structure of a gallery generated by Aperture, virtually all photo management apps produce galleries with a similar structure. Regardless of the application used, you should find: A group of html files including index and details pages A folder of large size image files A folder of thumbnails Once you have identified the structure used by your application, as we have done here, it will be a simple task to translate these instructions. Section 5: Referencing Files Over the Internet Now we can talk about how to reference these files and gallery pages so that we can create a script to generate a KML file that includes these references. When we identify a file over the internet, it is not enough to use the filename, e.g. 'thumb-1.jpg', or even the absolute and relative path to the file on the local computer. In fact these paths are most likely not valid as far as your web server is concerned. Instead we need to know how to reference our files such that they can be accessed over the global internet, and the web more specifically. In other words, we need to be able to generate a URL (Uniform Resource Locator) which unambiguously describes the location of our files. The formal details of exactly what comprises a URL5; are more complicated than may be obvious at first, but most of us are familiar with the typical URL, like this one: http://www.ietf.org/rfc/rfc1630.txt which describes the location of a document titled "Universal Resource Identifiers in WWW" that just so happens to define the formal details of what comprises a URL. http://www.ietf.org This portion of the address is enough to describe the location of a particular web server over the public internet. In fact it does a little more than just specify the location of a machine. The http:// portion is called the scheme and it identifies a particular protocol (i.e. a set of rules governing communication) and a related application, namely the web. What I just said isn't quite correct; at one time, HTTP was used exclusively by the web, but that's no longer true. Many internet-based applications use the protocol because the popularity of the web ensures that data sent via HTTP isn't blocked or otherwise disrupted. You may not be accustomed to thinking of it as such, but the web itself is a highly-distributed, network-based application. /rfc/ This portion of the address specifies a directory on the server. It is equivalent to an absolute path on your local computer. The leading forward slash is the root of the web server's public document directory. Assuming no trickiness on the part of the server, all content lives under the document root. This tells us that rfc/ is a sub-directory contained within the document root. Though this directory happens to be located immediately under the root, this certainly need not be the case. In fact these paths can get quite long. We have now discussed all of the URL except for: rfc1630.txt which is the name of a specific file. The filename is no different than the filenames on your local computer. Let's manually construct a path to one of the large-n.html pages of the gallery we have created. The address of my server is robreed.net, so I know that the beginning of my URL will be: http://robreed.net I keep all of my galleries together within a photos/ directory, which is contained in the document root. http://robreed.net/photos/ Within photos/, each gallery is given its own folder. The name of the folder I have created for this tutorial is 'tutorial_gallery'. Putting this all together, the following URL brings me to the root of my photo gallery: http://robreed.net/photos/tutorial_gallery/ We've already gone over the directory structure of the gallery, so it should make sense you to that when referring to the 'large-1.html' detail page, the complete URL will be: http://robreed.net/photos/tutorial_gallery/large-1.html the URL of the image that corresponds to that detail page is: http://robreed.net/photos/tutorial_gallery/pictures/picture-1.jpg and the thumbnail can be found at: http://robreed.net/photos/tutorial_gallery/thumbnails/thumb-1.jpg Notice that the address of the gallery is shared among all of these resources. Also, notice that resources of each type (e.g. the large images, thumbnails, and html pages) share a more specific address with files of that same type. If we use the term 'base address' to refer to the shared portions of these URLs, then we can talk about several significant base addresses: The gallery base address: http://robreed.net/photos/tutorial_gallery/ The html pages base address: http://robreed.net/photos/tutorial_gallery/ The images base address: http://robreed.net/photos/tutorial_gallery/pictures/ The thumbnails base address: http://robreed.net/photos/tutorial_gallery/thumbnails/ Note that given the structure of this particular gallery, the html pages base address and the gallery base address are identical. This need not be the case, and may not be for the gallery produced by your application. We can hard-code the base addresses into our script. For each photo, we need only append the associated filename to construct valid URLs to any of these resources. As the script runs, it will have access to the name of the file that it is currently evaluating, and so it will be a simple matter to generate the references we need as we go. At this point we have discussed almost everything we need to put together our script. We have: Created a gallery at our server, which includes our photos with metadata in tow Identified all of the metadata tags we need to extract from our photos with the script and the corresponding field names in our photo management application Determined all of the base addresses we need to generate references to our image files Section 6: KML The last thing we need to understand is the format of the KML files we want to produce. We've already looked at a fragment of KML. The full details can be found on Google's KML documentation pages , which include samples, tutorials and a complete reference for the format. A quick look at the reference is enough to see that the language includes many elements and attributes, the majority of which we will not be including in our files. That statement correctly implies it is not necessary for every KML file to include all elements and attributes. The converse however is not true, which is to say that every element and attribute contained in any KML file must be a part of the standard. A small subset of KML will get us most, if not all, of what you will typically see in Google Earth from other applications. Many of the features we will not be using deal with aspects of the language that are either: Not relevant to this project, e.g. ground overlays (GroundOverlay) which "draw an image overlay draped onto the terrain" Minute details for which the default values are sensible There is no need to feel shortchanged because we are covering only a subset of the language. With the basic structure in place and a solid understanding of how to script the generation of KML, you will be able to extend the project to include any of the other components of the language as you see fit. The structure of our KML file is as follows:  1.    <?xml version="1.0" encoding="UTF-8"?> 2.    <kml > 3.        <Document> 4.            <Folder> 5.                <name>$folder_name</name> 6.                <description>$folder_description</description> 7.                <Placemark> 8.                    <name>$placemark_name</name> 9.                    <Snippet maxLines="1"> 10.                        $placemark_snippet 11.                    </Snippet> 12.                    <description><![CDATA[ 13.                        $placemark_description 14.                    ]]></description> 15.                    <Point> 16.                        <coordinates>$longitude,$latitude </coordinates> 17.                    </Point> 18.                </Placemark> 19.            </Folder> 20.        </Document> 21.    </kml> Line 1: XML header Every valid KML file must start with this line and nothing else is allowed to appear before it. As I've already mentioned, KML is an XML-based language and XML requires this header. Line 2: Namespace declaration More specifically this is the KML namespace declaration, and it is another formality. The value of the >Line 3: <Document> is a container element representing the KML file itself. If we do not explicitly name the document by including a name element then Google Earth will use the name of the KML file as the Document element <name>. The Document container will appear on the Google Earth 'Sidebar' within the 'Places' panel. Optionally we can control whether the container is closed or open by default. (This setting can be toggled in Google Earth using a typical disclosure triangle.) There are many other elements and attributes that can be applied to the Document element. Refer to the KML Reference for the full details. Line 4: <Folder> is another container element. The files we produce will include a single <Folder> containing all of our Placemarks, where each Placemark represents a single image. We could create multiple Folder elements to group our Placemarks according to some significant criteria. Think of the Folder element as being similar to your operating system's concept of a folder. At this point, note the structure of the fragment. The majority of it is contained within the Folder element. Folder, in turn, is an element of Document which is itself within the <kml> container. It should make sense that everything in the file that is considered part of the language must be contained within the kml element. From the KML reference: A Folder is used to arrange other Features hierarchically (Folders, Placemarks, NetworkLinks, or Overlays). A Feature is visible only if it and all its ancestors are visible. Line 5: The name element identifies an object, in this case the Folder object. The text that appears between the name tags can be any plain text that will serve as an appropriate label.   Line 6: <description> is any text that seems to adequately describe the object. The description element supports both plain text and a subset of HTML. We'll consider issues related to using HTML in <description> at the discussion of Placemark, lines 12 - 14. Lines 7 - 17 define a <Placemark> element. Note that Placemark contains a number of elements that also appear in Folder, including <name> (line 8), and <description> (lines 12 - 14). These elements serve the same purpose for Placemark as they do for the Folder element, but of course they refer to a different object. I've said that <description> can include a subset of HTML in addition to plain text. Under XML, some characters have special meaning. You may need to use these characters as part of the HTML included in your descriptions. Angle brackets (<, >) for example surround tag names in HTML, but serve a similar purpose in XML. When they are used strictly as part of the content, we want the XML parser to ignore these characters. We can accomplish this a few different ways: We can use entity references, either numeric character references or character entity references, to indicate that the symbol appears as part of the data and should not be treated as part of the syntax of the language. The character '<', which is required to include an image as part of the description (something we will be doing), (e.g. <img src=... />) can safely be included as the character entity reference '&lt;' or the numeric character reference '&#60'. The character entity references may be easier to remember and recognize on sight but are limited to the small subset of characters for which they have been defined. The numeric references on the other hand can specify any ASCII character. Of the two types, numeric character references should be preferred. There are also Unicode entity references which can specify any character at all. In the simple case of embedding short bits of HTML in KML descriptions, we can avoid the complication of these references altogether by enclosing the entire description in a CDATA6 element, which instructs the XML parser to ignore any special characters that appear until the end of the block set off by the CDATA tags. Notice the string '<![CDATA[' immediately after the opening <description> tag within <Placemark>, and the string ]]> immediately before the closing </description> tag. If we simply place all of our HTML and plain text between those two strings, it will all be ignored by the parser and we are not required to deal with special characters individually. This is how we'll handle the issue. Lines 9 - 11: <Snippet> The KML reference does a good job of clearly describing this element. From the KML reference: In Google Earth, this description is displayed in the Places panel under the name of the feature. If a Snippet is not supplied, the first two lines of the <description> are used. In Google Earth, if a Placemark contains both a description and a Snippet, the <Snippet> appears beneath the Placemark in the Places panel, and the <description> appears in the Placemark's description balloon. This tag does not support HTML markup. <Snippet> has a maxLines attribute, an integer that specifies the maximum number of lines to display. Default for maxLines is 2. Notice that in the block above at line 9, I have included a 'maxLines' attribute with a value of 1. Of course, you are free to substitute your own value for maxLines, or you can omit the attribute entirely to use the default value. The only element we have yet to review is <Point>, and again we need only look to the official reference for a nice description. From the KML reference: A geographic location defined by longitude, latitude, and (optional) altitude. When a Point is contained by a Placemark, the point itself determines the position of the Placemark's name and icon. <Point> in turn contains the element <coordinates> which is required. From the KML reference: A single tuple consisting of floating point values for longitude, latitude, and altitude (in that order). The reference also informs us that altitude is optional, and in fact we will not be generating altitude values. Finally the reference warns: Do not include spaces between the three values that describe a coordinate. This seems like an easy mistake to make. We'll need to be careful to avoid it. There will be a number of <Placemark> elements, one for each of our images. The question is how to handle these elements. The answer is that we'll treat KML as a 'fill in the blanks' style template. All of the structural and syntactic bits will be hard-coded, e.g. the XML header, namespace declaration, all of the element and attribute labels, and even the whitespace, which is not strictly required but will make it much easier for us to inspect the resulting files in a text editor. These components will form our template. The blanks are all of the text and html values of the various elements and attributes. We will use variables as place-holders everywhere we need dynamic data, i.e. values that change from one file to the next or one execution of the script to the next. Take a look at the strings I've used in the block above. $folder_name, $folder_description, $placemark_name, etc. For those of you unfamiliar with Perl, these are all valid variable names chosen to indicate where the variables slot into the structure. These are the same names used in the source file distributed with the tutorial. Section 7: Introduction to the Code At this point, having discussed every aspect of the project, we can succinctly describe how to write the code. We'll do this in 3 stages of increasing granularity. Firstly, we'll finish this tutorial with a natural language walk-through of the execution of the script. Secondly, if you look at the source file included with the project, you will notice immediately that comments dominate the code. Because instruction is as important an objective as the actual operation of the script, I use comments in the source to provide a running narration. For those of you who find this superabundant level of commenting a distraction, I'm distributing a second copy of the source file with much of the comments removed. Finally, there is the code itself. After all, source code is nothing more than a rigorously formal set of instructions that describe how to complete a task. Most programs, including this one, are a matter of transforming input in one form to output in another. In this very ge
Read more
  • 0
  • 0
  • 8682

article-image-configuration-manager-troubleshooting-toolkit
Packt
18 Jan 2016
8 min read
Save for later

The Configuration Manager Troubleshooting Toolkit

Packt
18 Jan 2016
8 min read
In this article by Peter Egerton and Gerry Hampson, the author of the book Troubleshooting System Center Configuration Manager you will be able to dive deeper in the troubleshoot Configuration Manager concepts. In order to successfully troubleshoot Configuration Manager, there are a number of tools that are recommended to be always kept in your troubleshooting toolkit. These include a mixture of Microsoft provided tools, third-party tools, and some community developed tools. Best of all is that they are free. As it could be expected with the broad scope of functionality within Configuration Manager, there are also quite a variety of different utilities out there, so we need to know where to use the right tool for the problem. We are going to take a look at some commonly used tools and some not so commonly used ones and see what they do and where we can use them. These are not necessarily the be all and end all, but they will certainly help us get on the way to solving problems and undoubtedly save some time. In this article, we are going to cover the following: Registry editor Group policy tools Log file viewer PowerShell Community tools (For more resources related to this topic, see here.) Registry Editor Also worth a mention is the Registry Editor that is built into Microsoft Windows on both server and client operating systems. Most IT administrators know this as regedit.exe and it is the default tool of choice for making any changes to, or just simply viewing the contents of a registry key or value. Many of the Configuration Manager roles and the clients allow us to make changes to enables features such as extended logging or manually changing policy settings by using the registry to do so. It should be noted that changing the registry is not something that should be taken lightly however, as making incorrect changes can result in creating more problems not just in Configuration Manager but the operating system as a whole. If we stick to the published settings though, we should be fine and this can be a fine tool while troubleshooting oddities and problems in a Configuration Manager environment. Group Policy Tools As Configuration Manager is a client management tool, there are certain features and settings on a client such as software updates that may conflict with settings defined in Group Policy. In particular, in larger organizations, it can often be useful to compare and contrast the settings that may conflict between Group Policy and Configuration Manager. Using integrated tools such as Resultant Set of Policy (RSoP) and Group Policy Result (gpresult.exe) or the Group Policy management console as part of the Remote Server Administration Tools (RSAT) can help identify where and why clients are not functioning as expected. We can then move forward and amend group policies as and where required using the Group Policy object editor. Used in combination, these tools can prove essential while dealing with Configuration Manager clients in particular. Log file viewer Those who have spent any time at all working with Configuration Manager will know that it contains quite a few log files, literally hundreds. We will go through the log files in more detail in the next chapter but we will need to use something to read the logs. We can use something as simple as Notepad and to an extent there are some advantages with using this as it is a no nonsense text reader. Having said that, generally speaking most people want a little more when it comes to reading Configuration Manager logs as they can often be long, complex, and frequently refreshed. We have already seen one example of a log viewer as part of the Configuration Manager Support Center, but Configuration Manager includes its own log file viewer that is tailored to the needs of troubleshooting the product logs. In Configuration Manager 2012 versions, we are provided with CMTrace.exe. The previous versions provided us with Trace32.exe or SMSTrace.exe. They are very similar tools but we will highlight some of the features of CMTrace which is the more modern of the two. To begin with, we can typically find CMTrace in the following locations: <INSTALL DRIVE>Program FilesMicrosoft Configuration ManagerToolsCMTrace.exe <INSTALL MEDIA>SMSSETUPTOOLSCMTrace.exe Those that are running Configuration Manager 2012 R2 and up also have CMTrace available out of the box in WinPE when running Operating System Deployments. We can simply hit F8 if we have command support enabled in the WinPE image and type CMTrace. This can also be added to the later stages of a task sequence when running in the full operating system by copying the file onto the hard disk. The single biggest advantage of using CMTrace over a standard text reader is that it is a tail reader which by default is refreshed every 500 milliseconds or, in others words, it will update the window as new lines are logged in the log file; we also have the functionality to pause the file too. The other functionality of CMTrace is to allow filtering of the log based on certain conditions and there is also a highlight feature which can highlight a whole line in yellow if a word we are looking for is found on the line. The program automatically highlights lines if certain words are found such as error or warning, which is useful but can also be a red herring at times, so this is something to be aware of if we come across logs with these key words. We can also merge log files; this is particularly useful when looking at time critical incidents, as we can analyze data from multiple sources in the order they happened and understand the flow of information between the different components. PowerShell PowerShell is here to stay. A phrase often heard recently is Learn PowerShell or learn golf and like it or not you cannot get away from the emphasis on this homemade product from Microsoft. This is evident in just about all the current products, as PowerShell is so deeply embedded. Configuration Manager is no exception to this and although we cannot quite do everything you can in the console, there are an increasing number of cmdlets becoming available, more than 500 at the time of writing. So the question we may ask is where does this come into troubleshooting? Well, for the uninitiated in PowerShell, maybe it won't be the first tool they turn to, but with some experience, we can soon find that performing things like WMI queries and typical console tasks can be made quicker and slicker with PowerShell. If we prefer, we can also read log files from PowerShell and make remote changes to the machines. PowerShell can be a one-stop shop for our troubleshooting needs if we spend the time to pick up the skills. Community tools Finally, as user group community leaders, we couldn't leave this section out of the troubleshooting toolkit. Configuration Manager has such a great collection of community contributors that have likely to have been through our troubleshooting pain before us and either blog about it, post it on a forum or create a fix for it. There is such an array of free tools out there that people share that we cannot ignore them. Outside of troubleshooting specifically, some of the best add-ons available for Configuration Manager are community contributions whether that be from individuals or businesses. There are so many utilities which are ever evolving and not all will suit your needs, but if we browse the Microsoft TechNet galleries, Codeplex and GitHub, you are sure find a great resource to meet your requirements. Why not get involved with a user group too, in terms of troubleshooting, this is probably one of the best things I personally could recommend. It gives access to a network of people who work on the same product as us and are often using them in the same way, so it is quite likely that someone has seen our problem before and can fast forward us to a solution. Microsoft TechNet Galleries:https://www gallery.technet.microsoft.com/ Codeplex: https://www.codeplex.com/ GitHub: https://www.github.com/ Summary In this article, you learned about various troubleshoot Configuration Manager tools such as Registry editor, Group policy tools, Log file viewer, PowerShell, and Community tools. Resources for Article: Further resources on this subject: Basic Troubleshooting Methodology [article] Monitoring and Troubleshooting Networking [article] Troubleshooting your BAM Applications [article]
Read more
  • 0
  • 0
  • 8682

article-image-tips-and-tricks-getting-started-opengl-and-glsl-40
Packt
03 Aug 2011
14 min read
Save for later

Tips and Tricks for Getting Started with OpenGL and GLSL 4.0

Packt
03 Aug 2011
14 min read
  OpenGL 4.0 Shading Language Cookbook Over 60 highly focused, practical recipes to maximize your OpenGL Shading language use  Introduction The first step towards using the OpenGL Shading Language version 4.0 is to create a program that utilizes the latest version of the OpenGL API. GLSL programs don't stand on their own, they must be a part of a larger OpenGL program. In this article, we will see some tips on getting a basic OpenGL/GLSL program up and running and some techniques for communication between the OpenGL application and the shader (GLSL) program. There isn't any GLSL programming in this article, but don't worry, we'll jump into GLSL with both feet in the next article. First, let's start with some background. The OpenGL Shading Language The OpenGL Shading Language (GLSL) is now a fundamental and integral part of the OpenGL API. Going forward, every program written using OpenGL will internally utilize one or several GLSL programs. These "mini-programs" written in GLSL are often referred to as shader programs, or simply shaders. A shader program is one that runs on the GPU, and as the name implies, it (typically) implements the algorithms related to the lighting and shading effects of a 3-dimensional image. However, shader programs are capable of doing much more than just implementing a shading algorithm. They are also capable of performing animation, tessellation, and even generalized computation. The field of study dubbed GPGPU (General Purpose Computing on Graphics Processing Units) is concerned with utilization of GPUs (often using specialized APIs such as CUDA or OpenCL) to perform general purpose computations such as fluid dynamics, molecular dynamics, cryptography, and so on. Shader programs are designed to be executed directly on the GPU and often in parallel. For example, a fragment shader might be executed once for every pixel, with each execution running simultaneously on a separate GPU thread. The number of processors on the graphics card determines how many can be executed at one time. This makes shader programs incredibly efficient, and provides the programmer with a simple API for implementing highly parallel computation. The computing power available in modern graphics cards is impressive. The following table shows the number of shader processors available for several models in the NVIDIA GeForce 400 series cards (source: http://en.wikipedia.org/wiki/Comparison_of_Nvidia_graphics_processing_units). Shader programs are intended to replace parts of the OpenGL architecture referred to as the fixed-function pipeline. The default lighting/shading algorithm was a core part of this fixedfunction pipeline. When we, as programmers, wanted to implement more advanced or realistic effects, we used various tricks to force the fixed-function pipeline into being more flexible than it really was. The advent of GLSL helped by providing us with the ability to replace this "hard-coded" functionality with our own programs written in GLSL, thus giving us a great deal of additional flexibility and power. In fact, recent (core) versions of OpenGL not only provide this capability, but they require shader programs as part of every OpenGL program. The old fixed-function pipeline has been deprecated in favor of a new programmable pipeline, a key part of which is the shader program written in GLSL. Profiles: Core vs. Compatibility OpenGL version 3.0 introduced a deprecation model, which allowed for the gradual removal of functions from the OpenGL specification. Functions or features can now be marked as deprecated, meaning that they are expected to be removed from a future version of OpenGL. For example, immediate mode rendering using glBegin/glEnd was marked deprecated in version 3.0 and removed in version 3.1. In order to maintain backwards compatibility, the concept of compatibility profiles was introduced with OpenGL 3.2. A programmer who is writing code intended for a particular version of OpenGL (with older features removed) would use the so-called core profile. Someone who also wanted to maintain compatibility with older functionality could use the compatibility profile. It may be somewhat confusing that there is also the concept of a full vs. forward compatible context, which is distinguished slightly from the concept of a core vs. compatibility profile. A context that is considered forward compatible basically indicates that all deprecated functionality has been removed. In other words, if a context is forward compatible, it only includes functions that are in the core, but not those that were marked as deprecated. A full context supports all features of the selected version. Some window APIs provide the ability to select full or forward compatible status along with the profile. The steps for selecting a core or compatibility profile are window system API dependent. For example, in recent versions of Qt (at least version 4.7), one can select a 4.0 core profile using the following code: QGLFormat format; format.setVersion(4,0); format.setProfile(QGLFormat::CoreProfile); QGLWidget *myWidget = new QGLWidget(format); (you can download the example code here) All programs in this article are designed to be compatible with an OpenGL 4.0 core profile. Using the GLEW Library to access the latest OpenGL functionality The OpenGL ABI (application binary interface) is frozen to OpenGL version 1.1 on Windows. Unfortunately for Windows developers, that means that it is not possible to link directly to functions that are provided in newer versions of OpenGL. Instead, one must get access to these functions by acquiring a function pointer at runtime. Getting access to the function pointers requires somewhat tedious work, and has a tendency to clutter your code. Additionally, Windows typically comes with a standard OpenGL header file that conforms to OpenGL 1.1. The OpenGL wiki states that Microsoft has no plans to update the gl.h and opengl32.lib that comes with their compilers. Thankfully, others have provided libraries that manage all of this for us by probing your OpenGL libraries and transparently providing the necessary function pointers, while also exposing the necessary functionality in its header files. One such library is called GLEW (OpenGL Extension Wrangler). Getting ready Download the GLEW distribution from http://glew.sourceforge.net. There are binaries available for Windows, but it is also a relatively simple matter to compile GLEW from source (see the instructions on the website: http://glew.sourceforge.net). Place the header files glew.h and wglew.h from the GLEW distribution into a proper location for your compiler. If you are using Windows, copy the glew32.lib to the appropriate library directory for your compiler, and place the glew32.dll into a system-wide location, or the same directory as your program's executable. Full installation instructions for all operating systems and common compilers are available on the GLEW website. How to do it... To start using GLEW in your project, use the following steps: Make sure that, at the top of your code, you include the glew.h header before you include the OpenGL header files: #include <GL/glew.h> #include <GL/gl.h> #include <GL/glu.h> In your program code, somewhere just after the GL context is created (typically in an initialization function), and before any OpenGL functions are called, include the following code: GLenum err = glewInit(); if( GLEW_OK != err ) { fprintf(stderr, "Error initializing GLEW: %sn", glewGetErrorString(err) ); } That's all there is to it! How it works... Including the glew.h header file provides declarations for the OpenGL functions as function pointers, so all function entry points are available at compile time. At run time, the glewInit() function will scan the OpenGL library, and initialize all available function pointers. If a function is not available, the code will compile, but the function pointer will not be initialized. There's more... GLEW includes a few additional features and utilities that are quite useful. GLEW visualinfo The command line utility visualinfo can be used to get a list of all available extensions and "visuals" (pixel formats, pbuffer availability, and so on). When executed, it creates a file called visualinfo.txt, which contains a list of all the available OpenGL, WGL, and GLU extensions, including a table of available visuals (pixel formats, pbuffer availability, and the like). GLEW glewinfo The command line utility glewinfo lists all available functions supported by your driver. When executed, the results are printed to stdout. Checking for extension availability at runtime You can also check for the availability of extensions by checking the status of some GLEW global variables that use a particular naming convention. For example, to check for the availability of ARB_vertex_program, use something like the following: if ( ! GLEW_ARB_vertex_program ) { fprintf(stderr, "ARB_vertex_program is missing!n"); ... } See also Another option for managing OpenGL extensions is the GLee library (GL Easy Extension). It is available from http://www.elf-stone.com/glee.php and is open source under the modified BSD license. It works in a similar manner to GLEW, but does not require runtime initialization. Using the GLM library for mathematics Mathematics is core to all of computer graphics. In earlier versions, OpenGL provided support for managing coordinate transformations and projections using the standard matrix stacks (GL_MODELVIEW and GL_PROJECTION). In core OpenGL 4.0, however, all of the functionality supporting the matrix stacks has been removed. Therefore, it is up to us to provide our own support for the usual transformation and projection matrices, and then to pass them into our shaders. Of course, we could write our own matrix and vector classes to manage this, but if you're like me, you prefer to use a ready-made, robust library. One such library is GLM (OpenGL Mathematics) written by Christophe Riccio. Its design is based on the GLSL specification, so the syntax is very similar to the mathematical support in GLSL. For experienced GLSL programmers, this makes it very easy to use. Additionally, it provides extensions that include functionality similar to some of the much-missed OpenGL functions such as glOrtho, glRotate, or gluLookAt. Getting ready Download the latest GLM distribution from http://glm.g-truc.net. Unzip the archive file, and copy the glm directory contained inside to anywhere in your compiler's include path. How to do it... Using the GLM libraries is simply a matter of including the core header file (highlighted in the following code snippet) and headers for any extensions. We'll include the matrix transform extension, and the transform2 extension. #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtx/transform2.hpp> The GLM classes are then available in the glm namespace. The following is an example of how you might go about making use of some of them. glm::vec4 position = glm::vec4( 1.0f, 0.0f, 0.0f, 1.0f ); glm::mat4 view = glm::lookAt( glm::vec3(0.0,0.0,5.0), glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,1.0,0.0) ); glm::mat4 model = glm::mat4(1.0f); model = glm::rotate( model, 90.0f, glm::vec3(0.0f,1.0f,0.0) ); glm::mat4 mv = view * model; glm::vec4 transformed = mv * position; How it works... The GLM library is a header-only library. All of the implementation is included within the header files. It doesn't require separate compilation and you don't need to link your program to it. Just placing the header files in your include path is all that's required! The preceding example first creates a vec4 (four coordinate vector) representing a position. Then it creates a 4x4 view matrix by using the glm::lookAt function from the transform2 extension. This works in a similar fashion to the old gluLookAt function. In this example, we set the camera's location at (0,0,5), looking towards the origin, with the "up" direction in the direction of the Y-axis. We then go on to create the modeling matrix by first storing the identity matrix in the variable model (via the constructor: glm::mat4(1.0f)), and multiplying by a rotation matrix using the glm::rotate function. The multiplication here is implicitly done by the glm::rotate function. It multiplies its first parameter by the rotation matrix that is generated by the function. The second parameter is the angle of rotation (in degrees), and the third parameter is the axis of rotation. The net result is a rotation matrix of 90 degrees around the Y-axis. Finally, we create our model view matrix (mv) by multiplying the view and model variables, and then using the combined matrix to transform the position. Note that the multiplication operator has been overloaded to behave in the expected way. As stated above, the GLM library conforms as closely as possible to the GLSL specification, with additional features that go beyond what you can do in GLSL. If you are familiar with GLSL, GLM should be easy and natural to use. Swizzle operators (selecting components using commands like: foo.x, foo.xxy, and so on) are disabled by default in GLM. You can selectively enable them by defining GLM_SWIZZLE before including the main GLM header. The GLM manual has more detail. For example, to enable all swizzle operators you would do the following: #define GLM_SWIZZLE #include <glm/glm.hpp> There's more... It is not recommended to import all of the GLM namespace using a command like: using namespace glm; This will most likely cause a number of namespace clashes. Instead, it is preferable to import symbols one at a time, as needed. For example: #include <glm/glm.hpp> using glm::vec3; using glm::mat4; Using the GLM types as input to OpenGL GLM supports directly passing a GLM type to OpenGL using one of the OpenGL vector functions (with the suffix "v"). For example, to pass a mat4 named proj to OpenGL we can use the following code: #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> ... glm::mat4 proj = glm::perspective( viewAngle, aspect, nearDist, farDist ); glUniformMatrix4fv(location, 1, GL_FALSE, &proj[0][0]); See also The GLM website http://glm.g-truc.net has additional documentation and examples. Determining the GLSL and OpenGL version In order to support a wide range of systems, it is essential to be able to query for the supported OpenGL and GLSL version of the current driver. It is quite simple to do so, and there are two main functions involved: glGetString and glGetIntegerv. How to do it... The code shown below will print the version information to stdout: const GLubyte *renderer = glGetString( GL_RENDERER ); const GLubyte *vendor = glGetString( GL_VENDOR ); const GLubyte *version = glGetString( GL_VERSION ); const GLubyte *glslVersion = glGetString( GL_SHADING_LANGUAGE_VERSION ); GLint major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); printf("GL Vendor : %sn", vendor); printf("GL Renderer : %sn", renderer); printf("GL Version (string) : %sn", version); printf("GL Version (integer) : %d.%dn", major, minor); printf("GLSL Version : %sn", glslVersion); How it works... Note that there are two different ways to retrieve the OpenGL version: using glGetString and glGetIntegerv. The former can be useful for providing readable output, but may not be as convenient for programmatically checking the version because of the need to parse the string. The string provided by glGetString(GL_VERSION) should always begin with the major and minor versions separated by a dot; however, the minor version could be followed with a vendor-specific build number. Additionally, the rest of the string can contain additional vendor-specific information and may also include information about the selected profile. glGetInteger is available in OpenGL 3.0 or greater. The queries for GL_VENDOR and GL_RENDERER provide additional information about the OpenGL driver. The call glGetString(GL_VENDOR) returns the company responsible for the OpenGL implementation. The call to glGetString(GL_RENDERER) provides the name of the renderer which is specific to a particular hardware platform (such as "ATI Radeon HD 5600 Series"). Note that both of these do not vary from release to release, so can be used to determine the current platform. Of more importance to us is the call to glGetString(GL_SHADING_LANGUAGE_VERSION) which provides the supported GLSL version number. This string should begin with the major and minor version numbers separated by a period, but similar to the GL_VERSION query, may include other vendor-specific information. There's more... It is often useful to query for the supported extensions of the current OpenGL implementation. In versions prior to OpenGL 3.0, one could retrieve a full, space separated list of extension names with the following code: GLubyte *extensions = glGetString(GL_EXTENSIONS); The string that is returned can be extremely long and parsing it can be susceptible to error if not done carefully. In OpenGL 3.0, a new technique was introduced, and the above functionality was deprecated (and finally removed in 3.1). Extension names are now indexed and can be individually queried by index. We use the glGetStringi variant for this. For example, to get the name of the extension stored at index i, we use: glGetString(GL_EXTENSIONS, i). To print a list of all extensions, we could use the following code: GLint nExtensions; glGetIntegerv(GL_NUM_EXTENSIONS, &nExtensions); for( int i = 0; i < nExtensions; i++ ) printf("%sn", glGetStringi( GL_EXTENSIONS, i ) );
Read more
  • 0
  • 0
  • 8677

article-image-essentials-vmware-vsphere
Packt
09 Jul 2015
7 min read
Save for later

Essentials of VMware vSphere

Packt
09 Jul 2015
7 min read
In this article by Puthiyavan Udayakumar, author of the book VMware vSphere Design Essentials, we will cover the following topics: Essentials of designing VMware vSphere The PPP framework The challenges and encounters faced on virtual infrastructure (For more resources related to this topic, see here.) Let's get started with understanding the essentials of designing VMware vSphere. Designing is nothing but assembling and integrating VMware vSphere infrastructure components together to form the baseline for a virtualized datacenter. It has the following benefits: Saves power consumption Decreases the datacenter footprint and helps towards server consolidation Fastest server provisioning On-demand QA lab environments Decreases hardware vendor dependency Aids to move to the cloud Greater savings and affordability Superior security and High Availability Designing VMware vSphere Architecture design principles are usually developed by the VMware architect in concurrence with the enterprise CIO, Infrastructure Architecture Board, and other key business stakeholders. From my experience, I would always urge you to have frequent meetings to observe functional requirements as much as possible. This will create a win-win situation for you and the requestor and show you how to get things done. Please follow your own approach, if it works. Architecture design principles should be developed by the overall IT principles specific to the customer's demands, if they exist. If not, they should be selected to ensure positioning of IT strategies in line with business approaches. In nutshell, architect should aim to form an effective architecture principles that fulfills the infrastructure demands, following are high level principles that should be followed across any design: Design mission and plans Design strategic initiatives External influencing factors When you release a design to the customer, keep in mind that the design must have the following principles: Understandable and robust Complete and consistent Stable and capable of accepting continuous requirement-based changes Rational and controlled technical diversity Without the preceding principles, I wouldn't recommend you to release your design to anyone even for peer review. For every design, irrespective of the product that you are about to design, try the following approach; it should work well but if required I would recommend you make changes to the approach. The following approach is called PPP, which will focus on people's requirements, the product's capacity, and the process that helps to bridge the gap between the product capacity and people requirements: The preceding diagram illustrates three entities that should be considered while designing VMware vSphere infrastructure. Please keep in mind that your design is just a product designed by a process that is based on people's needs. In the end, using this unified framework will aid you in getting rid of any known risks and its implications. Functional requirements should be meaningful; while designing, please make sure there is a meaning to your design. Selecting VMware vSphere from other competitors should not be a random pick, you should always list the benefits of VMware vSphere. Some of them are as follows: Server consolidation and easy hardware changes Dynamic provisioning of resources to your compute node Templates, snapshots, vMotion, DRS, DPM, High Availability, fault tolerance, auto monitoring, and solutions for warnings and alerts Virtual Desktop Infrastructure (VDI), building a disaster recovery site, fast deployments, and decommissions The PPP framework Let's explore the components that integrate to form the PPP framework. Always keep in mind that the design should consist of people, processes, and products that meet the unified functional requirements and performance benchmark. Always expect the unexpected. Without these metrics, your design is incomplete; PPP always retains its own decision metrics. What does it do, who does it, and how is it done? We will see the answers in the following diagrams: The PPP Framework helps you to get started with requirements gathering, design vision, business architecture, infrastructure architecture, opportunities and solutions, migration planning, fixing the tone for implementing and design governance. The following table illustrates the essentials of the three-dimensional approach and the basic questions that are required to be answered before you start designing or documenting about designing, which will in turn help to understand the real requirements for a specific design: Phase Description Key components Product Results of what? In what hardware will the VM reside? What kind of CPU is required? What is the quantity of CPU, RAM, storage per host/VM? What kind of storage is required? What kind of network is required? What are the standard applications that need to be rolled out? What kind of power and cooling are required? How much rack and floor space is demanded? People Results of who? Who is responsible for infrastructure provisioning? Who manages the data center and supplies the power? Who is responsible for implementation of the hardware and software patches? Who is responsible for storage and back up? Who is responsible for security and hardware support? Process Results of how? How should we manage the virtual infrastructure? How should we manage hosted VMs? How should we provision VM on demand? How should a DR site be active during a primary site failure? How should we provision storage and backup? How should we take snapshots of VMs? How should we monitor and perform periodic health checks? Before we start to apply the PPP framework on VMware vSphere, we will discuss the list of challenges and encounters faced on the virtual infrastructure. List of challenges and encounters faced on the virtual infrastructure In this section, we will see a list of challenges and encounters faced with virtual infrastructure due to the simple reason that we fail to capture the functional and non-functional demands of business users, or do not understand the fit-for-purpose concept: Resource Estimate Misfire: If you underestimate the amount of memory required up-front, you could change the number of VMs you attempt to run on the VMware ESXi host hardware. Resource unavailability: Without capacity management and configuration management, you cannot create dozens or hundreds of VMs on a single host. Some of the VMs could consume all resources, leaving other VMs unknown. High utilization: An army of VMs can also throw workflows off-balance due to the complexities they can bring to provisioning and operational tasks. Business continuity: Unlike a PC environment, VMs cannot be backed up to an actual hard drive. This is why 80 percent of IT professionals believe that virtualization backup is a great technological challenge. Security: More than six out of ten IT professionals believe that data protection is a top technological challenge. Backward compatibility: This is especially challenging for certain apps and systems that are dependent on legacy systems. Monitoring performance: Unlike physical servers, you cannot monitor the performance of VMs with common hardware resources such as CPU, memory, and storage. Restriction of licensing: Before you install software on virtual machines, read the license agreements; they might not support this; hence, by hosting on VMs, you might violate the agreement. Sizing the database and mailbox: Proper sizing of databases and mailboxes is really critical to the organization's communication systems and for applications. Poor design of storage and network: A poor storage design or a networking design resulting from a failure to properly involve the required teams within an organization is a sure-fire way to ensure that this design isn't successful. Summary In this article we covered a brief introduction of the essentials of designing VMware vSphere which focused on the PPP framework. We also had look over the challenges and encounters faced on the virtual infrastructure. Resources for Article: Further resources on this subject: Creating and Managing VMFS Datastores [article] Networking Performance Design [article] The Design Documentation [article]
Read more
  • 0
  • 0
  • 8677

article-image-glsl-40-using-subroutines-select-shader-functionality
Packt
10 Aug 2011
7 min read
Save for later

GLSL 4.0: Using Subroutines to Select Shader Functionality

Packt
10 Aug 2011
7 min read
OpenGL 4.0 Shading Language Cookbook Over 60 highly focused, practical recipes to maximize your OpenGL Shading language use         In many ways it is similar to function pointers in C. A uniform variable serves as the pointer and is used to invoke the function. The value of this variable can be set from the OpenGL side, thereby binding it to one of a few possible definitions. The subroutine's function definitions need not have the same name, but must have the same number and type of parameters and the same return type. A single shader could be written to provide several shading algorithms intended for use on different objects within the scene. When rendering the scene, rather than swapping shader programs (or using a conditional statement), we can simply change the subroutine's uniform variable to choose the appropriate shading algorithm as each object is rendered. Since performance is crucial in shader programs, avoiding a conditional statement or a shader swap can be very valuable. With subroutines, we can implement the functionality of a conditional statement or shader swap without the computational overhead. In the following image, we see an example of a rendering that was created using subroutines. The teapot on the left is rendered with the full ADS shading model, and the teapot on the right is rendered with diffuse shading only. A subroutine is used to switch between shader functionality. Getting ready As with previous recipes, provide the vertex position at attribute location 0 and the vertex normal at attribute location 1. Uniform variables for all of the ADS coefficients should be set from the OpenGL side, as well as the light position and the standard matrices. We'll assume that, in the OpenGL application, the variable programHandle contains the handle to the shader program object. How to do it... To create a shader program that uses a subroutine to switch between pure-diffuse and ADS shading, use the following code: Use the following code for the vertex shader: #version 400 subroutine vec3 shadeModelType( vec4 position, vec3 normal); subroutine uniform shadeModelType shadeModel; layout (location = 0) in vec3 VertexPosition; layout (location = 1) in vec3 VertexNormal; out vec3 LightIntensity; struct LightInfo { vec4 Position; // Light position in eye coords. vec3 La; // Ambient light intensity vec3 Ld; // Diffuse light intensity vec3 Ls; // Specular light intensity }; uniform LightInfo Light; struct MaterialInfo { vec3 Ka; // Ambient reflectivity vec3 Kd; // Diffuse reflectivity vec3 Ks; // Specular reflectivity float Shininess; // Specular shininess factor }; uniform MaterialInfo Material; uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform mat4 ProjectionMatrix; uniform mat4 MVP; void getEyeSpace( out vec3 norm, out vec4 position ) { norm = normalize( NormalMatrix * VertexNormal); position = ModelViewMatrix * vec4(VertexPosition,1.0); } subroutine( shadeModelType ) vec3 phongModel( vec4 position, vec3 norm ) { // The ADS shading calculations go here (see: "Using // functions in shaders," and "Implementing // per-vertex ambient, diffuse and specular (ADS) shading") ... } subroutine( shadeModelType ) vec3 diffuseOnly( vec4 position, vec3 norm ) { vec3 s = normalize( vec3(Light.Position - position) ); return Light.Ld * Material.Kd * max( dot(s, norm), 0.0 ); } void main() { vec3 eyeNorm; vec4 eyePosition; // Get the position and normal in eye space getEyeSpace(eyeNorm, eyePosition); // Evaluate the shading equation. This will call one of // the functions: diffuseOnly or phongModel. LightIntensity = shadeModel( eyePosition, eyeNorm ); gl_Position = MVP * vec4(VertexPosition,1.0); } Use the following code for the fragment shader: #version 400 in vec3 LightIntensity; layout( location = 0 ) out vec4 FragColor; void main() { FragColor = vec4(LightIntensity, 1.0); } In the OpenGL application, compile and link the above shaders into a shader program, and install the program into the OpenGL pipeline. Within the render function of the OpenGL application, use the following code: GLuint adsIndex = glGetSubroutineIndex( programHandle, GL_VERTEX_SHADER,"phongModel" ); GLuint diffuseIndex = glGetSubroutineIndex(programHandle, GL_VERTEX_SHADER, "diffuseOnly"); glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &adsIndex); ... // Render the left teapot glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &diffuseIndex); ... // Render the right teapot How it works... In this example, the subroutine is defined within the vertex shader. The first step involves declaring the subroutine type. subroutine vec3 shadeModelType( vec4 position, vec3 normal); This defines a new subroutine type with the name shadeModelType. The syntax is very similar to a function prototype, in that it defines a name, a parameter list, and a return type. As with function prototypes, the parameter names are optional. After creating the new subroutine type, we declare a uniform variable of that type named shadeModel. subroutine uniform shadeModelType shadeModel; This variable serves as our function pointer and will be assigned to one of the two possible functions in the OpenGL application. We declare two functions to be part of the subroutine by prefixing their definition with the subroutine qualifier: subroutine ( shadeModelType ) This indicates that the function matches the subroutine type, and therefore its header must match the one in the subroutine type definition. We use this prefix for the definition of the functions phongModel and diffuseOnly. The diffuseOnly function computes the diffuse shading equation, and the phongModel function computes the complete ADS shading equation. We call one of the two subroutine functions by utilizing the subroutine uniform shadeModel within the main function. LightIntensity = shadeModel( eyePosition, eyeNorm ); Again, this call will be bound to one of the two functions depending on the value of the subroutine uniform shadeModel, which we will set within the OpenGL application. Within the render function of the OpenGL application, we assign a value to the subroutine uniform with the following steps. First, we query for the index of each subroutine function using glGetSubroutineIndex. The first argument is the program handle. The second is the shader stage. In this case, the subroutine is defined within the vertex shader, so we use GL_VERTEX_SHADER here. The third argument is the name of the subroutine. We query for each function individually and store the indexes in the variables adsIndex and diffuseIndex. To select the appropriate subroutine function, we need to set the value of the subroutine uniform shadeModel. To do so, we call glUniformSubroutinesuiv. This function is designed for setting multiple subroutine uniforms at once. In our case, of course, we are setting only a single uniform. The first argument is the shader stage (GL_VERTEX_SHADER), the second is the number of uniforms being set, and the third is a pointer to an array of subroutine function indexes. Since we are setting a single uniform, we simply provide the address of the GLuint variable containing the index, rather than a true array of values. Of course, we would use an array if multiple uniforms were being set. In general, the array of values provided as the third argument is assigned to subroutine uniform variables in the following way. The ith element of the array is assigned to the subroutine uniform variable with index i. Since we have provided only a single value, we are setting the subroutine uniform at index zero. You may be wondering, "How do we know that our subroutine uniform is located at index zero? We didn't query for the index before calling glUniformSubroutinesuiv!" The reason that this code works is that we are relying on the fact that OpenGL will always number the indexes of the subroutines consecutively starting at zero. If we had multiple subroutine uniforms, we could (and should) query for their indexes using glGetSubroutineUniformLocation, and then order our array appropriately. Finally, we select the phongModel function by setting the uniform to adsIndex and then render the left teapot. We then select the diffuseOnly function by setting the uniform to diffuseIndex and render the right teapot. There's more... A subroutine function defined in a shader can match multiple subroutine types. In that case, the subroutine qualifier can contain a comma-separated list of subroutine types. For example, if a subroutine matched the types type1 and type2, we could use the following qualifier: subroutine( type1, type2 ) This would allow us to use subroutine uniforms of differing types to refer to the same subroutine function. Summary With subroutines we can implement the functionality of a conditional statement or shader swap without the computational overhead. Further resources on this subject: Tips and Tricks for Getting Started with OpenGL and GLSL 4.0 [Article] OpenGL 4.0: Using Uniform Blocks and Uniform Buffer Objects [Article] OpenGL 4.0: Building a C++ Shader Program Class [Article] The Basics of GLSL 4.0 Shaders [Article] GLSL 4.0: Discarding Fragments to Create a Perforated Look [Article]
Read more
  • 0
  • 0
  • 8671

article-image-user-interaction-and-email-automation-symfony-13-part2
Packt
18 Nov 2009
8 min read
Save for later

User Interaction and Email Automation in Symfony 1.3: Part2

Packt
18 Nov 2009
8 min read
Automated email responses Symfony comes with a default mailer library that is based on Swift Mailer 4, the detailed documentation is available from their web site at http://swiftmailer.org. After a user has signed up to our mailing list, we would like an email verification to be sent to the user's email address. This will inform the user that he/she has signed up, and will also ask him or her to activate their subscription. To use the library, we have to complete the following three steps: Store the mailing settings in the application settings file. Add the application logic to the action. Create the email template. Adding the mailer settings to the application Just like all the previous settings, we should add all the settings for sending emails to the module.yml file for the signup module. This will make it easier to implement any modifications required later. Initially, we should set variables like the email subject, the from name, the from address, and whether we want to send out emails within the dev environment. I have added the following items to our signup module's setting file, apps/frontend/config/module.yml: dev: mailer_deliver: true all: mailer_deliver: true mailer_subject: Milkshake Newsletter mailer_from_name: Tim mailer_from_email: no-reply@milkshake All of the settings can be contained under the all label. However, you can see that I have introduced a new label called dev. These labels represent the environments, and we have just added a specific variable to the dev environment. This setting will allow us to eventually turn off the sending of emails while in the dev environment. Creating the application logic Triggering the email should occur after the user's details have been saved to the database. To demonstrate this, I have added the highlighted amends to the submit action in the apps/frontend/modules/signup/actions/actions.class.php file, as shown in the following code: public function executeSubmit(sfWebRequest $request) { $this->form = new NewsletterSignupForm(); if ($request->isMethod('post') && $this->form-> bindAndSave($request->getParameter($this->form-> getName()))) { //Include the swift lib require_once('lib/vendor/swift-mailer/lib/swift_init.php'); try{ //Sendmail $transport = Swift_SendmailTransport::newInstance(); $mailBody = $this->getPartial('activationEmail', array('name' => $this->form->getValue('first_name'))); $mailer = Swift_Mailer::newInstance($transport); $message = Swift_Message::newInstance(); $message->setSubject(sfConfig::get('app_mailer_subject')); $message->setFrom(array(sfConfig:: get('app_mailer_from_email') => sfConfig::get('app_mailer_from_name'))); $message->setTo(array($this->form->getValue('email')=> $this-> form->getValue('first_name'))); $message->setBody($mailBody, 'text/html'); if(sfConfig::get('app_mailer_deliver')) { $result = $mailer->send($message); } } catch(Exception $e) { var_dump($e); exit; } $this->redirect('@signup'); } //Use the index template as it contains the form $this->setTemplate('index'); } Symfony comes with a sfMailer class that extends Swift_Mailer. To send mails you could simply implement the following Symfony method: $this->getMailer()->composeAndSend('from@example.com', 'to@example.com', 'Subject', 'Body'); Let's walk through the process: Instantiate the Swift Mailer. Retrieve the email template (which we will create next) using the $this->getPartial('activationEmail', array('name' => $this->form->getValue('first_name'))) method. Breaking this down, the function itself retrieves a partial template. The first argument is the name of the template to retrieve (that is activationEmail in our example) which, if you remember, means that the template will be called _activationEmail.php. The next argument is an array that contains variables related to the partial template. Here, I have set a name variable. The value for the name is important. Notice how I have used the value within the form object to retrieve the first_name value. This is because we know that these values have been cleaned and are safe to use. Set the subject, from, to, and the body items. These functions are Swift Mailer specific: setSubject(): It takes a string as an argument for the subject setFrom(): It takes the name and the mailing address setTo(): It takes the name and the mailing address setBody(): It takes the email body and mime type. Here we passed in our template and set the email to text/html Finally we send the email. There are more methods in Swift Mailer. Check out the documentation on the Swift Mailer web site (http://swiftmailer.org/). The partial email template Lastly, we need to create a partial template that will be used in the email body. In the templates folder of the signup module, create a file called _activationEmail.php and add the following code to it: Hi <?php echo $name; ?>, <br /><br /> Thank you for signing up to our newsletter. <br /><br /> Thank you, <br /> <strong>The Team</strong> The partial is no different from a regular template. We could have opted to pass on the body as a string, but using the template keeps our code uniform. Our signup process now incorporates the functionality to send an email. The purpose of this example is to show you how to send an automated email using a third-party library. For a real application, you should most certainly implement a two-phase option wherein the user must verify his or her action. Flashing temporary values Sometimes it is necessary to set a temporary variable for one request, or make a variable available to another action after forwarding but before having to delete the variable. Symfony provides this level of functionality within the sfUser object known as a flash variable. Once a flash variable has been set, it lasts until the end of the overall request before it is automatically destroyed. Setting and getting a flash attribute is managed through two of the sfUser methods. Also, you can test for a flash variable's existence using the third method of the methods listed here: $this->getUser()->setFlash($name, $value, $persist = true) $this->getUser()->getFlash($name) $this->getUser()->hasFlash($name) Although a flash variable will be available by default when a request is forwarded to another action, setting the argument to false will delete the flash variable before it is forwarded. To demonstrate how useful flash variables can be, let's readdress the signup form. After a user submits the signup form, the form is redisplayed. I further mentioned that you could create another action to handle a 'thank you' template. However, by using a flash variable we will not have to do so. As a part of the application logic for the form submission, we can set a flash variable. Then after the action redirects the request, the template can test whether there is a flash variable set. If there is one, the template should show a message rather than the form. Let's add the $this->getUser()->setFlash() function to the submit action in the apps/frontend/modules/signup/actions/actions.class.php file: //Include the swift lib require_once('lib/vendor/swift-mailer/lib/swift_init.php'); //set Flash $this->getUser()->setFlash('Form', 'completed'); try{ I have added the flash variable just under the require_once() statement. After the user has submitted a valid form, this flash variable will be set with the name of the Form and have a value completed. Next, we need to address the template logic. The template needs to check whether a flash variable called Form is set. If it is not set, the template shows the form. Otherwise it shows a thank you message. This is implemented using the following code: <?php if(!$sf_user->hasFlash('Form')): ?> <form action="<?php echo url_for('@signup_submit') ?>" method="post" name="Newsletter"> <div style="height: 30px;"> <div style="width: 150px; float: left"> <?php echo $form['first_name']->renderLabel() ?></div> <?php echo $form['first_name']->render(($form['first_name']-> hasError())? array('class'=>'boxError'): array ('class'=>'box')) ?> <?php echo ($form['first_name']->hasError())? ' <span class="errorMessage">* '.$form['first_name']->getError(). '</span>': '' ?> <div style="clear: both"></div> </div> .... </form> <?php else: ?><h1>Thank you</h1>You are now signed up.<?php endif ?> The form is now wrapped inside an if/else block. Accessing the flash variables from a template is done through $sf_user. To test if the variable has been set, I have used the hasFlash() method, $sf_user->hasFlash('Form'). The else part of the statement contains the text rather than the form. Now if you submit your form, you will see the result as shown in the following screenshot: We have now implemented an entire module for a user to sign up for our newsletter. Wouldn't it be really good if we could add this module to another application without all the copying, pasting, and fixing?
Read more
  • 0
  • 0
  • 8654
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-iphone-javascript-installing-frameworks
Packt
23 Jun 2011
14 min read
Save for later

iPhone JavaScript: Installing Frameworks

Packt
23 Jun 2011
14 min read
  iPhone JavaScript Cookbook Clear and practical recipes for building web applications using JavaScript and AJAX without having to learn Objective-C or Cocoa         Read more about this book       (For more resources related to this subject, see here.) Introduction Many web applications implement common features independent of the final purpose for which they have been designed. Functionalities and features such as authentication, forms validation, retrieving records from a database, caching, logging, and pagination are very common in modern web applications. As a developer, surely you have implemented one or more of these features in your applications more than once. Good developers and software engineers insist on concepts, such as modularity, reusability, and encapsulation; as a consequence you can find a lot of books, papers, and articles talking about how to design your software using these techniques. In fact, modern and popular methodologies, such as Extreme Programming, Scrum, and Test-driven Development are based on those principles. Although this approach sounds very appealing in theory, it might be complicated to carry it out in practice. Developing any kind of software from scratch for running in any platform is undoubtedly a hard task. Complexity grows up when the target platform, operating system, or machine has its own specific rules and mechanisms. Some tools can make our job less complicated but only one kind of them is definitely a safe bet. It is here when we meet frameworks, a set of proven code that offers common functionality and standard structures for software development. This code makes our life much easier without reinventing the wheel and gives a skeleton to our applications, making sure that we're doing things correctly. In addition, frameworks avoid starting from scratch once more. From a technical point of view, most frameworks are a set of libraries implementing functions, classes, and methods. Using frameworks, we can save time and money, writing less code due to its code skeleton, and features implemented on it. Usually, frameworks force us to follow standards and they offer well-proven code avoiding common mistakes for beginners. Tasks such as testing, maintenance, and deployment are easier to do using frameworks due to the tools and mechanisms included. On the other hand, the learning curve could be a big and difficult drawback for beginners. Through this article, we'll learn how to install the main frameworks for JavaScript, HTML, and CSS development for iPhone. All of them offer a base to develop applications with a consistent and native look and feel using different methods. While some of them are focused on the user interface, others allow using AJAX in an efficient and easy way. Even some frameworks allow building native applications from the original code of the web application. We have the chance to choose which is better to fulfill our requirements; it is even possible to use more than one of these solutions for the same application. For our recipes, we'll use the following frameworks: iUI: This is focused on the look and feel of iPhone and consists of CSS files, images, and a small JavaScript library. Its objective is to get a web application running on the device with a consistent interface such as a native application. This framework establishes a correspondence between HTML tags and conventions used for developing native applications. UiUIKit: Using a set of CSS and image files, it provides a coherent system for building web applications with a graphic interface such as native iPhone applications. The features offered for this framework are very similar to iUI. XUI: This is a pure JavaScript library specific for mobile development. It has been designed to be faster and lighter than other similar libraries, such as jQuery, MooTools, and prototype. iWebKit: This is developed specifically for Apple's devices and is compatible with CSS3 standard; it helps to write web applications or websites with minimum HTML knowledge. Its modular design supports plugins for adding new features and we can build and use the themes for UI customization. WebApp.Net: This framework comes loaded with JavaScript, CSS, and image files for developing web application for mobile devices that uses WebKit engine in its web browsers. Besides building interfaces, this framework includes functionality to use AJAX in an easy and efficient way. PhoneGap: This is designed to minimize efforts for developing native mobile applications for different operating systems, platforms, and devices. It is based on the WORE (Write once, run anywhere) principle and it allows conversion from a web application into a native application. It supports many platforms and operating systems, such as iOS, Android, webOS, Symbian, and BlackBerry OS. Apple Dashcode: Formally, this is a software development tool for Mac OS X included in Leopard and Snow Leopard versions, and focused on widget development for these operating systems. However, the last versions allow you to write web applications for iPhone and other iOS devices offering a graphic interface builder. Installing the iUI framework This recipe shows how to download and install the iUI framework on different operating systems. Particularly, we'll cover Microsoft Windows, Mac OS X, and GNU/Linux. Getting ready The first step is to install and get ready; some tools need to be downloaded and decompressed. As computer users, we know how to decompress files using software such as WinZip, Ark, or the built-in utility on Mac OS X. You will surely have installed a web browser on your computer. If you are a Linux or Mac developer, you already know how to use curl or wget. These tools are very useful for quick download and you only need to use the command line through applications such as GNOME Terminal, Konsole, iTerm, or Terminal. iUI is an open source project, so you can download the code for free. The open source project releases some stable versions packed and ready to download, but it is also possible to download a development version. This one could be suitable if you prefer working with the latest changes made by the official developers contributing to the project. Due to this, developers are using Mercurial version control and thus we'll need to install a client for it to get access to this code. How to do it... iUI is an open source project so you can download the code for free. Open your favorite web browser and enter this URL: http://code.google.com/p/iui/downloads/list In that web page, you'll see a list with files that refer to different release versions of this framework. Clicking on the link corresponding to the latest release's drives takes you to a new web page that shows you a new link for the file. Click on it for instant downloading. (Move the mouse over the image to enlarge it.) If you are a GNU/Linux user or a Mac developer you will be used to command line. Open your terminal application and launch this command from your desired directory: $ wget http://iui.googlecode.com/files/iui-0.31.tar.gz Once you have downloaded the tarball file, it's time to extract its content to a specific folder on our computer. WinZip and WinRAR are the most popular tools to do this task on Windows. Linux distributions, by default, install similar tools such as File Roller and Ark. Double-clicking from the download window of the Safari browser will extract the files directly to your default folder on your Mac, which is usually called Downloads. For command-line enthusiasts, execute the following command: $ tar -zxvf iui-0.31.tar.gz How it works... After decompressing the downloaded file, you'll find a folder with different subfolders and files. The most important is a subfolder called iui that contains CSS, images, and JavaScript files for building our web applications for iPhone. We need to copy this subfolder to our working folder where other application files reside. Sharing this framework across different web applications is possible; you only need to put the iUI at a place where these applications have permissions to access. Usually, this place is a folder under the DocumentRoot of your web server. If you're planning to write a high load application, it would be a good idea to use a cloud or CDN (Content Delivery Network) service such as Amazon Simple Storage Services (Amazon S3) for hosting and serving static HTML, CSS, JavaScript, and image files. Installing the iUI framework is a straightforward process. You simply download and decompress one file, and then copy one folder into an other, which has permission to be accessed by the web server. Apache is one of the most used and extended web servers in the world. Other popular options are Internet Information Server (IIS), lighttpd, and nginx. Apache web server is installed by default on Mac OS X; most of the operating systems based on Linux and UNIX offer binary packages for easy installation and you can find binary files for installing on Windows as well. IIS was designed for Windows operating systems, meanwhile, lighttpd and nginx are winning popularity and are used on UNIX systems as Linux's distros, FreeBSD, and OpenBSD. Ubuntu Linux uses /var/www/ directory as the main DocumentRoot for Apache. So, in order to share iUI framework across applications, you can copy the folder to the other folder by executing this command: $ cp -r iui-0.31/ui /var/www/iui If you are a Mac user, your target directory will be /Library/WebServer/Documents/iui. There's more... Inside the samples subfolder, you'll find some files showing capabilities of this framework, including HTML and PHP files. Some examples need a web server with PHP support but you can test others using Safari web browser or an other WebKit's browser such as Safari or Google Chrome. Open index.html with a web browser and use it as your starting point. If you prefer to use the latest version in development from the version control, you'll need to install a Mercurial client. Most of the GNU/Linux distribution such as Fedora, Debian, and Ubuntu includes binary packages ready to install them. Usually, the name of the binary package is mercurial. The following command will install the client on Ubuntu Linux: $ sudo apt-get install mercurial Mercurial is an open source project and offers a binary file ready to install for Mac OS X and Windows systems. If you're using one of these, go to the following page and download the specific file for your operating system and version: http://mercurial.selenic.com/downloads/ After downloading, you can install the client using the regular process for your operating system. Mac users will find a ZIP file containing a binary package. For Windows, the distributed file is a MSI (Microsoft Installer), ready for self-installation after clicking on it. Despite that the client of this version control was developed for the command line, we can find some GUI tools online such as TortoiseHG for Windows. These tools are intuitive and user-friendly, allowing an interactive use between the user and the source files hosted in the version control system. TortoiseHG can be downloaded from the same web page as the Mercurial client. Finally, we'll download the version development of the iUI framework executing the following command: $ hg clone https://iui.googlecode.com/hg/ iui The new iui folder includes all files of the iUI framework. We should copy this folder to our DocumentRoot. If you want to know more about this framework, point your browser at the official wiki project: http://code.google.com/p/iui/w/list Also, taking a look at the complete code of the project may be interesting for advanced developers or just for people wanting to learn more about internal details: http://code.google.com/p/iui/source/browse Installing the UiUIKit framework UiUIKit is the short name of the Universal iPhone UI Kit framework. The development of this framework is carried out through an open source project hosted in Google Code and is distributed under the GNU Public License v3. Let's see how to install it on different operating systems. Getting ready As the main project file is distributed as a ZIP file, we'll need to use one tool for decompressing these kind of files. Most of the modern operating systems include tools for this process. As seen in the previous recipe, we can use wget or curl programs for downloading the files. If you are planning to read the source code or you'd like to use the current development version of the framework, you'll need a Subversion client as the UiUIKit project is working with this open source version control. How to do it... Open your web browser and type the following URL: http://code.google.com/p/iphone-universal/downloads/list After downloading, click on the link for the latest version from the main list, for instance, the link called UiUIKit-2.1.zip. The next page will show you a different link for this file that represents the version 2.1 of the UiUIKit framework. Click on the link and the file will start downloading immediately. Mac users will see how the Safari browser shows a window with the content of the compressed file, which is a folder called UiUIKit, which is stored in the default folder for downloads. Command line's fans can use these simple commands from their favorite terminal tool: $ cd ~$ curl -O http://iphone-universal.googlecode.com/files/UiUIKit-2.1.zip After downloading, don't forget to decompress the file on your web-specific directory. The commands given next execute this action on Linux and Mac OS X systems: $ cd /var/www/$ unzip ~/UiUIKit-2.1.zip How it works... The main folder of the UiUIKit framework contains two subfolders called images and stylesheets. The first one includes many images used to get a native look for web applications on the iPhone. The other one offers a CSS file called iphone.css. We only need the images subfolder with its graphic files and the CSS file. In order to use this framework in our projects, we need to allow our HTML files access to the images and the CSS file of the framework. These files should be in a folder with permissions for the web server. For example, we'll have a directory structure for our new web application for iPhone as follows: myapp/ index.html images/ actionButtons.png apple-touch-icon.png backButton.png toolButton.png whiteButton.png first.html second.html stylesheets/ iphone.css Remember that this framework doesn't include HTML files; we only need a bunch of the graphic files and one stylesheet file. The HTML files showed in the previous example will be our own files created for the web application. We'll also find a lot of examples on different HTML files located in the root directory, outside the mentioned subfolders. These files are not required for development but they can be very useful to show how to use some features and functionalities. There's more... For an initial contact with the capabilities of the framework it would be interesting to take a look at the examples included in the main directory of the framework. We can load the index.html in our browser. This file is an index to the different examples and offers a native interface for the iPhone. Safari could be used but is better to access from a real iPhone device. Subversion is a well-proven version control used by many developers, companies, and, of course, open source projects. UiUIKit is an example of these projects using this popular version control. So, to access the latest version in development, we'll need a client to download it. Popular Linux distributions, including Ubuntu and Debian have binary packages ready to install. For instance, the following command is enough to install it on Ubuntu Linux: $ sudo apt-get install subversion The last versions of Mac OS X, including Leopard and Snow Leopard, includes a Subversion client ready to use. For Windows, you can download Slik SVN available for 32-bit and 64-bits platforms; installation programs can be downloaded from: http://www.sliksvn.com/en/download. When you are sure that your client is running, you could execute it for getting the latest development version of the UiUIKit framework. Mac and Linux users will execute the following command: $ svn checkout http://iphone-universal.googlecode.com/svn/trunk/ UiUIKit All information related to the UiUIKit framework project could be found at: http://code.google.com/p/iphone-universal/
Read more
  • 0
  • 0
  • 8652

article-image-planning-desktop-virtualization
Packt
16 Oct 2014
3 min read
Save for later

Planning Desktop Virtualization

Packt
16 Oct 2014
3 min read
 This article by Andy Paul, author of the book Citrix XenApp® 7.5 Virtualization Solutions, explains the VDI and its building blocks in detail. (For more resources related to this topic, see here.) The building blocks of VDI The first step in understanding Virtual Desktop Infrastructure (VDI) is to identify what VDI means to your environment. VDI is an all-encompassing term for most virtual infrastructure projects. For this book, we will use the definitions cited in the following sections for clarity. Hosted Virtual Desktop (HVD) Hosted Virtual Desktop is a machine running a single-user operating system such as Windows 7 or Windows 8, sometimes called a desktop OS, which is hosted on a virtual platform within the data center. Users remotely access a desktop that may or may not be dedicated but runs with isolated resources. This is typically a Citrix XenDesktop virtual desktop, as shown in the following figure:   Hosted Virtual Desktop model; each user has dedicated resources Hosted Shared Desktop (HSD) Hosted Shared Desktop is a machine running a multiuser operating system such as Windows 2008 Server or Windows 2012 Server, sometimes called a server OS, possibly hosted on a virtual platform within the data center. Users remotely access a desktop that may be using shared resources among multiple users. This will historically be a Citrix XenApp published desktop, as demonstrated in the following figure:   Hosted Shared Desktop model; each user shares the desktop server resources Session-based Computing (SBC) With Session-based Computing, users remotely access applications or other resources on a server running in the data center. These are typically client/server applications. This server may or may not be virtualized. This is a multiuser environment, but the users do not access the underlying operating system directly. This will typically be a Citrix XenApp hosted application, as shown in the following figure:   Session-based computing model; each user accesses applications remotely, but shares resources Application virtualization In application virtualization, applications are centrally managed and distributed, but they are locally executed. This may be in conjunction with, or separate from, the other options mentioned previously. Application virtualization typically involves application isolation, allowing the applications to operate independently of any other software. This will be an example of Citrix XenApp offline applications as well as Citrix profiled applications, Microsoft App-V application packages, and VMware ThinApp solutions. Have a look at the following figure:   Application virtualization model; the application packages execute locally The preceding list is not a definitive list of options, but it serves to highlight the most commonly used elements of VDI. Other options include client-side hypervisors for local execution of a virtual desktop, hosted physical desktops, and cloud-based applications. Depending on the environment, all of these components can be relevant. Summary In this article, we learned the VDI and understood its building blocks in detail. Resources for Article: Further resources on this subject: Installation and Deployment of Citrix Systems®' CPSM [article] Designing, Sizing, Building, and Configuring Citrix VDI-in-a-Box [article] Introduction to Citrix XenDesktop [article]
Read more
  • 0
  • 0
  • 8650

article-image-exploring-and-interacting-materials-using-blueprints
Packt
23 Jul 2015
16 min read
Save for later

Exploring and Interacting with Materials using Blueprints

Packt
23 Jul 2015
16 min read
In this article by Brenden Sewell, author of the book Blueprints Visual Scripting for Unreal Engine, we will cover the following topics: Exploring materials Creating our first Blueprint When setting out to develop a game, one of the first steps toward exploring your idea is to build a prototype. Fortunately, Unreal Engine 4 and Blueprints make it easier than ever to quickly get the essential gameplay functionality working so that you can start testing your ideas sooner. To develop some familiarity with the Unreal editor and Blueprints, we will begin by prototyping simple gameplay mechanics using some default assets and a couple of Blueprints. (For more resources related to this topic, see here.) Exploring materials Earlier, we set for ourselves the goal of changing the color of the cylinder when it is hit by a projectile. To do so, we will need to change the actor's material. A material is an asset that can be added to an actor's mesh (which defines the physical shape of the actor) to create its look. You can think of a material as paint applied on top of an actor's mesh or shape. Since an actor's material determines its color, one method of changing the color of an actor is to replace its material with a material of a different color. To do this, we will first be creating a material of our own. It will make an actor appear red. Creating materials We can start by creating a new folder inside the FirstPersonBP directory and calling it Materials. Navigate to the newly created folder and right-click inside the empty space in the content browser, which will generate a new asset creation popup. From here, select Material to create a new material asset. You will be prompted to give the new material a name, which I have chosen to call TargetRed. Material Properties and Blueprint Nodes Double-click on TargetRed to open a new editor tab for editing the material, like this: You are now looking at Material Editor, which shares many features and conventions with Blueprints. The center of this screen is called the grid, and this is where we will place all the objects that will define the logic of our Blueprints. The initial object you see in the center of the grid screen, labeled with the name of the material, is called a node. This node, as seen in the previous screenshot, has a series of input pins that other material nodes can attach to in order to define its properties. To give the material a color, we will need to create a node that will give information about the color to the input labeled Base Color on this node. To do so, right-click on empty space near the node. A popup will appear, with a search box and a long list of expandable options. This shows all the available Blueprint node options that we can add to this Material Blueprint. The search box is context sensitive, so if you start typing the first few letters of a valid node name, you will see the list below shrink to include only those nodes that include those letters in the name. The node we are looking for is called VectorParameter, so we start typing this name in the search box and click on the VectorParameter result to add that node to our grid: A vector parameter in the Material Editor allows us to define a color, which we can then attach to the Base Color input on the tall material definition node. We first need to give the node a color selection. Double-click on the black square in the middle of the node to open Color Picker. We want to give our target a bright red color when it is hit, so either drag the center point in the color wheel to the red section of the wheel, or fill in the RGB or Hex values manually. When you have selected the shade of red you want to use, click on OK. You will notice that the black box in your vector parameter node has now turned red. To help ourselves remember what parameter or property of the material our vector parameter will be defining, we should name it color. You can do this by ensuring that you have the vector parameter node selected (indicated by a thin yellow highlight around the node), and then navigating to the Details panel in the editor. Enter a value for Parameter Name, and the node label will change automatically: The final step is to link our color vector parameter node to the base material node. With Blueprints, you can connect two nodes by clicking and dragging one output pin to another node's input pin. Input pins are located on the left-hand side of a node, while output pins are always located to the right. The thin line that connects two nodes that have been connected in this way is called a wire. For our material, we need to click and drag a wire from the top output pin of the color node to the Base Color input pin of the material node, as shown in the following screenshot: Adding substance to our material We can optionally add some polish to our material by taking advantage of some of the other input pins on the material definition node. 3D objects look unrealistic with flat, single color materials applied, but we can add additional reflectiveness and depth by setting a value for the materials Metallic and Roughness inputs. To do so, right click in empty grid space and type scalar into the search box. The node we are looking for is called ScalarParameter. Once you have a scalar parameter node, select it, and go to the Details panel. A scalar parameter takes a single float value (a number with decimal values). Set Default Value to 0.1, as we want any additive effects to our material to be subtle. We should also change Parameter Name to Metallic. Finally, we click and drag the output pin from our Metallic node to the Metallic input pin of the material definition node. We want to make an additional connection to the Roughness parameter, so right-click on the Metallic node we just created and select Duplicate. This will generate a copy of that node, without the wire connection. Select this duplicate Metallic node and then change the Parameter Name field in the Details panel to Roughness. We will keep the same default value of 0.1 for this node. Now click and drag the output pin from the Roughness node to the Roughness input pin of the Material definition node. The final result of our Material Blueprint should look like what is shown in the following screenshot: We have now made a shiny red material. It will ensure that our targets will stand out when they are hit. Click on the Save button in the top-left corner of the editor to save the asset, and click again on the tab labeled FirstPersonExampleMap to return to your level. Creating our first Blueprint We now have a cylinder in the world, and the material we would like to apply to the cylinder when shot. The final piece of the interaction will be the game logic that evaluates that the cylinder has been hit, and then changes the material on the cylinder to our new red material. In order to create this behavior and add it to our cylinder, we will have to create a Blueprint. There are multiple ways of creating a Blueprint, but to save a couple of steps, we can create the Blueprint and directly attach it to the cylinder we created in a single click. To do so, make sure you have the CylinderTarget object selected in the Scene Outliner panel, and click on the blue Blueprint/Add Script button at the top of the Details panel. You will then see a path select window. For this project, we will be storing all our Blueprints in the Blueprints folder, inside the FirstPersonBP folder. Since this is the Blueprint for our CylinderTarget actor, leaving the name of the Blueprint as the default, CylinderTarget_Blueprint, is appropriate. CylinderTarget_Blueprint should now appear in your content browser, inside the Blueprints folder. Double-click on this Blueprint to open a new editor tab for the Blueprint. We will now be looking at the Viewport view of our cylinder. From here, we can manipulate some of the default properties of our actor, or add more components, each of which can contain their own logic to make the actor more complex. for creating a simple Blueprint attached to the actor directly. To do so, click on the tab labeled Event Graph above the Viewport window. Exploring the Event Graph panel The Event Graph panel should look very familiar, as it shares most of the same visual and functional elements as the Material Editor we used earlier. By default, the event graph opens with three unlinked event nodes that are currently unused. An event refers to some action in the game that acts as a trigger for a Blueprint to do something. Most of the Blueprints you will create follow this structure: Event (when) | Conditionals (if) | Actions (do). This can be worded as follows: when something happens, check whether X, Y, and Z are true, and if so, do this sequence of actions. A real-world example of this might be a Blueprint that determines whether or not I have fired a gun. The flow is like this: WHEN the trigger is pulled, IF there is ammo left in the gun, DO fire the gun. The three event nodes that are present in our graph by default are three of the most commonly used event triggers. Event Begin Play triggers actions when the player first begins playing the game. Event Actor Begin Overlap triggers actions when another actor begins touching or overlapping the space containing the existing actor controlled by the Blueprint. Event Tick triggers attached actions every time a new frame of visual content is displayed on the screen during gameplay. The number of frames that are shown on the screen within a second will vary depending on the power of the computer running the game, and this will in turn affect how often Event Tick triggers the actions. We want to trigger a "change material" action on our target every time a projectile hits it. While we could do this by utilizing the Event Actor Begin Overlap node to detect when a projectile object was overlapping with the cylinder mesh of our target, we will simplify things by detecting only when another actor has hit our target actor. Let's start with a clean slate, by clicking and dragging a selection box over all the default events and hitting the Delete key on the keyboard to delete them. Detecting a hit To create our hit detection event, right-click on empty graph space and type hit in the search box. The Event Hit node is what we are looking for, so select it when it appears in the search results. Event Hit triggers actions every time another actor hits the actor controlled by this Blueprint. Once you have the Event Hit node on the graph, you will notice that Event Hit has a number of multicolored output pins originating from it. The first thing to notice is the white triangle pin that is in the top-right corner of the node. This is the execution pin, which determines the next action to be taken in a sequence. Linking the execution pins of different nodes together enables the basic functionality of all Blueprints. Now that we have the trigger, we need to find an action that will enable us to change the material of an actor. Click and drag a wire from the execution pin to the empty space to the right of the node. Dropping a wire into empty space like this will generate a search window, allowing you to create a node and attach it to the pin you are dragging from in a single operation. In the search window that appears, make sure that the Context Sensitive box is checked. This will limit the results in the search window to only those nodes that can actually be attached to the pin you dragged to generate the search window. With Context Sensitive checked, type set material in the search box. The node we want to select is called Set Material (StaticMeshComponent). If you cannot find the node you are searching for in the context-sensitive search, try unchecking Context Sensitive to find it from the complete list of node options. Even if the node is not found in the context-sensitive search, there is still a possibility that the node can be used in conjunction with the node you are attempting to attach it to. The actions in the Event Hit node can be set like this: Swapping a material Once you have placed the Set Material node, you will notice that it is already connected via its input execution pin to the Event Hit node's output execution pin. This Blueprint will now fire the Set Material action whenever the Blueprint's actor hits another actor. However, we haven't yet set up the material that will be called when the Set Material action is called. Without setting the material, the action will fire but not produce any observable effect on the cylinder target. To set the material that will be called, click on the drop-down field labeled Select Asset underneath Material inside the Set Material node. In the asset finder window that appears, type red in the search box to find the TargetRed material we created earlier. Clicking on this asset will attach it to the Material field inside the Set Material node. We have now done everything we need with this Blueprint to turn the target cylinder red, but before the Blueprint can be saved, it must be compiled. Compiling is the process used to convert the developer-friendly Blueprint language into machine instructions that tell the computer what operations to perform. This is a hands-off process, so we don't need to concern ourselves with it, except to ensure that we always compile our Blueprint scripts after we assemble them. To do so, hit the Compile button in the top-left corner of the editor toolbar, and then click on Save. Now that we have set up a basic gameplay interaction, it is wise to test the game to ensure that everything is happening the way we expect. Click on the Play button, and a game window will appear directly above the Blueprint Editor. Try both shooting and running into the CylinderTarget actor you created. Improving the Blueprint When we run the game, we see that the cylinder target does change colors upon being hit by a projectile fired from the player's gun. This is the beginning of a framework of gameplay that can be used to get enemies to respond to the player's actions. However, you also might have noticed that the target cylinder changes color even when the player runs into it directly. Remember that we wanted the cylinder target to become red only when hit by a player projectile, and not because of any other object colliding with it. Unforeseen results like this are common whenever scripting is involved, and the best way to avoid them is to check your work by playing the game as you construct it as often as possible. To fix our Blueprint so that the cylinder target changes color only in response to a player projectile, return to the CylinderTarget_Blueprint tab and look at the Event Hit node again. The remaining output pins on the Event Hit node are variables that store data about the event that can be passed to other nodes. The color of the pins represents the kind of data variable it passes. Blue pins pass objects, such as actors, whereas red pins contain a boolean (true or false) variable. You will learn more about these pin types as we get into more complicated Blueprints; for now, we only need to concern ourselves with the blue output pin labeled Other, which contains the data about which other actor performed the hitting to fire this event. This will be useful in order for us to ensure that the cylinder target changes color only when hit by a projectile fired from the player, rather than changing color because of any other actors that might bump into it. To ensure that we are only triggering in response to a player projectile hit, click and drag a wire from the Other output pin to empty space. In this search window, type projectile. You should see some results that look similar to the following screenshot. The node we are looking for is called Cast To FirstPersonProjectile: FirstPersonProjectile is a Blueprint included in Unreal Engine 4's First Person template that controls the behavior of the projectiles that are fired from your gun. This node uses casting to ensure that the action attached to the execution pin of this node occurs only if the actor hitting the cylinder target matches the object referenced by the casting node. When the node appears, you should already see a blue wire between the Other output pin of the Event Hit node and the Object pin of the casting node. If not, you can generate it manually by clicking and dragging from one pin to the other. You should also remove the connections between the Event Hit and Set Material node execution pins so that the casting node can be linked between them. Removing a wire between two pins can be done by holding down the Alt key and clicking on a pin. Once you have linked the three nodes, the event graph should look like what is shown in the following screenshot: Now compile, save, and click on the play button again to test. This time, you should notice that the cylinder target retains its default color when you walk up and touch it, but does turn red when fired upon by your gun. Summary In this article, the skills you have learned will serve as a strong foundation for building more complex interactive behavior. You may wish to spend some additional time modifying your prototype to include a more appealing layout, or feature faster moving targets. One of the greatest benefits of Blueprint's visual scripting is the speed at which you can test new ideas, and each additional skill that you learn will unlock exponentially more possibilities for game experiences that you can explore and prototype. Resources for Article: Further resources on this subject: Creating a Brick Breaking Game [article] Configuration and Handy Tweaks for UDK [article] Unreal Development Toolkit: Level Design HQ [article]
Read more
  • 0
  • 0
  • 8649

article-image-your-first-swift-2-project
Packt
16 Feb 2016
29 min read
Save for later

Your First Swift 2 Project

Packt
16 Feb 2016
29 min read
After the release of Xcode 6 in 2014, it has been possible to build Swift applications for iOS and OS X and submit them to the App Store for publication. This article will present both a single view application and a master-detail application, and use these to explain the concepts behind iOS applications, as well as introduce classes in Swift. In this article, we will present the following topics: How iOS applications are structured Single-view iOS applications Creating classes in Swift Protocols and enums in Swift Using XCTest to test Swift code Master-detail iOS applications The AppDelegate and ViewController classes (For more resources related to this topic, see here.) Understanding iOS applications An iOS application is a compiled executable along with a set of supporting files in a bundle. The application bundle is packaged into an archive file to be installed onto a device or upload to the App Store. Xcode can be used to run iOS applications in a simulator, as well as testing them on a local device. Submitting an application to the App Store requires a developer signing key, which is included as part of the Apple Developer Program at https://developer.apple.com. Most iOS applications to date have been written in Objective-C, a crossover between C and Smalltalk. With the advent of Swift, it is likely that many developers will move at least parts of their applications to Swift for performance and maintenance reasons. Although Objective-C is likely to be around for a while, it is clear that Swift is the future of iOS development and probably OS X as well. Applications contain a number of different types of files, which are used both at compile time and also at runtime. These files include the following: The Info.plist file, which contains information about which languages the application is localized for, what the identity of the application is, and the configuration requirements, such as the supported interface types (iPad, iPhone, and Universal), and orientations (Portrait, Upside Down, Landscape Left, and Landscape Right) Zero or more interface builder files with a .xib extension, which contain user interface screens (which supersedes the previous .nib files) Zero or more image asset files with a .xcassets extension, which store groups of related icons at different sizes, such as the application icon or graphics for display on screen (which supersedes the previous .icns files) Zero or more storyboard files with a .storyboard extension, which are used to coordinate between different screens in an application One or more .swift files that contain application code Creating a single-view iOS application A single-view iOS application is one where the application is presented in a single screen, without any transitions or other views. This section will show how to create an application that uses a single view without storyboards. When Xcode starts, it displays a welcome message that includes the ability to create a new project. This welcome message can be redisplayed at any time by navigating to Window | Welcome to Xcode or by pressing Command + Shift + 1. Using the welcome dialog's Create a new Xcode project option, or navigating to File | New | Project..., or by pressing Command + Shift + N, create a new iOS project with Single View Application as the template, as shown in the following screenshot: When the Next button is pressed, the new project dialog will ask for more details. The product name here is SingleView with appropriate values for Organization Name and Identifier. Ensure that the language selected is Swift and the device type is Universal: The Organization Identifier is a reverse domain name representation of the organization, and the Bundle Identifier is the concatenation of the Organization Identifier with the Product Name. Publishing to the App Store requires that the Organization Identifier be owned by the publisher and is managed in the online developer center at https://developer.apple.com/membercenter/. When Next is pressed, Xcode will ask where to save the project and whether a repository should be created. The selected location will be used to create the product directory, and an option to create a Git repository will be offered. In 2014, Git became the most widely used version control system, surpassing all other distributed and centralized version-control systems. It would be foolish not to create a Git repository when creating a new Xcode project. When Create is pressed, Xcode will create the project, set up template files, and then initialize the Git repository locally or on a shared server. Press the triangular play button at the top-left of Xcode to launch the simulator: If everything has been set up correctly, the simulator will start with a white screen and the time and battery shown at the top of the screen: Removing the storyboard The default template for a single-view application includes a storyboard. This creates the view for the first (only) screen and performs some additional setup behind the scenes. To understand what happens, the storyboard will be removed and replaced with code instead. Most applications are built with one or more storyboards. The storyboard can be deleted by going to the project navigator, finding the Main.storyboard file, and pressing the Delete key or selecting Delete from the context-sensitive menu. When the confirmation dialog is shown, select the Move to Trash option to ensure that the file is deleted rather than just being removed from the list of files that Xcode knows about. To see the project navigator, press Command + 1 or navigate to View | Navigators | Show Project Navigator. Once the Main.storyboard file has been deleted, it needs to be removed from Info.plist, to prevent iOS from trying to open it at startup. Open the Info.plist file under the Supporting Files folder of SingleView. A set of key-value pairs will be displayed; clicking on the Main storyboard file base name row will present the (+) and (-) options. Clicking on the delete icon (-) will remove the line: Now, when the application is started, a black screen will be displayed. There are multiple Info.plist files that are created by Xcode's template; one file is used for the real application, while the other files are used for the test applications that get built when running tests. Setting up the view controller The view controller is responsible for setting up the view when it is activated. Typically, this is done through either the storyboard or the interface file. As these have been removed, the window and the view controller need to be instantiated manually. When iOS applications start, application:didFinishLaunchingWithOptions: is called on the corresponding UIApplicationDelegate. The optional window variable is initialized automatically when it is loaded from an interface file or a storyboard, but it needs to be explicitly initialized if the user interface is being implemented in code. Implement the application:didFinishLaunchingWithOptions: method in the AppDelegate class as follows: @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {   var window: UIWindow?   func application(application: UIApplication,    didFinishLaunchingWithOptions launchOptions:    [NSObject:AnyObject]?) -> Bool {     window = UIWindow()     window?.rootViewController = ViewController()     window?.makeKeyAndVisible()     return true   } } To open a class by name, press Command + Shift + O and type in the class name. Alternatively, navigate to File | Open Quickly... The final step is to create the view's content, which is typically done in the viewDidLoad method of the ViewController class. As an example user interface, a UILabel will be created and added to the view. Each view controller has an associated view property, and child views can be added with the addSubview method. To make the view stand out, the background of the view will be changed to black and the text color will be changed to white: class ViewController: UIViewController {   override func viewDidLoad() {     super.viewDidLoad()     view.backgroundColor = UIColor.blackColor()     let label = UILabel(frame:view.bounds)     label.textColor = UIColor.whiteColor()     label.textAlignment = .Center     label.text = "Welcome to Swift"       view.addSubview(label)   } } This creates a label, which is sized to the full size of the screen, with a white text color and a centered text alignment. When run, this displays Welcome to Swift on the screen. Typically, views will be implemented in their own class rather than being in-lined into the view controller. This allows the views to be reused in other controllers. When the screen is rotated, the label will be rotated off screen. Logic would need to be added in a real application to handle rotation changes in the view controller, such as willRotateToInterfaceOrientation, and to appropriately add rotations to the views using the transform property of the view. Usually, an interface builder file or storyboard would be used so that this is handled automatically. Swift classes, protocols, and enums Almost all Swift applications will be object oriented. Classes, such as Process from the CoreFoundation framework, and UIColor and UIImage from the UIKit framework, were used to demonstrate how classes can be used in applications. This section describes how to create classes, protocols, and enums in Swift. Classes in Swift A class is created in Swift using the class keyword, and braces are used to enclose the class body. The body can contain variables called properties, as well as functions called methods, which are collectively referred to as members. Instance members are unique to each instance, while static members are shared between all instances of that class. Classes are typically defined in a file named for the class; so a GitHubRepository class would typically be defined in a GitHubRepository.swift file. A new Swift file can be created by navigating to File | New | File… and selecting the Swift File option under iOS. Ensure that it is added to the Tests and UITests targets as well. Once created, implement the class as follows: class GitHubRepository {   var id:UInt64 = 0   var name:String = ""   func detailsURL() -> String {     return "https://api.github.com/repositories/(id)"   } } This class can be instantiated and used as follows: let repo = GitHubRepository() repo.id = 1 repo.name = "Grit" repo.detailsURL() // returns https://api.github.com/repositories/1 It is possible to create static members, which are the same for all instances of a class. In the GitHubRepository class, the api URL is likely to remain the same for all invocations, so it can be refactored into a static property: class GitHubRepository {   // does not work in Swift 1.0 or 1.1   static let api = "https://api.github.com"   …   class func detailsURL(id:String) -> String {     return "(api)/repositories/(id)"   } } Now, if the api URL needs to be changed (for example, to support mock testing or to support an in-house GitHub Enterprise server), there is a single place to change it. Before Swift 2, a class variables are not yet supported error message may be displayed. To use static variables in Swift prior to version 2, a different approach must be used. It is possible to define computed properties, which are not stored but are calculated on demand. These have a getter (also known as an accessor) and optionally a setter (also known as a mutator). The previous example can be rewritten as follows: class GitHubRepository {   class var api:String {     get {       return "https://api.github.com"     }   }   func detailsURL() -> String {     return "(GitHubRepository.api)/repositories/(id)"   } } Although this is logically a read-only constant (there is no associated set block), it is not possible to define the let constants with accessors. To refer to a class variable, use the type name—which in this case is GitHubRepository. When the GitHubRepository.api expression is evaluated, the body of the getter is called. Subclasses and testing in Swift A simple Swift class with no explicit parent is known as a base class. However, classes in Swift frequently inherit from another class by specifying a superclass after the class name. The syntax for this is class SubClass:SuperClass{...}. Tests in Swift are written using the XCTest framework, which is included by default in Xcode templates. This allows an application to have tests written and then executed in place to confirm that no bugs have been introduced. XCTest replaces the previous testing framework OCUnit. The XCTest framework has a base class called XCTestCase that all tests inherit from. Methods beginning with test (and that take no arguments) in the test case class are invoked automatically when the tests are run. Test code can indicate success or failure by calling the XCTAssert* functions, such as XCTAssertEquals and XCTAssertGreaterThan. Tests for the GitHubRepository class conventionally exist in a corresponding GitHubRepositoryTest class, which will be a subclass of XCTestCase. Create a new Swift file by navigating to File | New | File... and choosing a Swift File under the Source category for iOS. Ensure that the Tests and UITests targets are selected but the application target is not. It can be implemented as follows: import XCTest class GitHubRepositoryTest: XCTestCase {   func testRepository() {     let repo = GitHubRepository()     repo.id = 1     repo.name = "Grit"     XCTAssertEqual(       repo.detailsURL(),       "https://api.github.com/repositories/1",       "Repository details"     )   } } Make sure that the GitHubRepositoryTest class is added to the test targets. If not added when the file is created, it can be done by selecting the file and pressing Command + Option + 1 to show the File Inspector. The checkbox next to the test target should be selected. Tests should never be added to the main target. The GitHubRepository class should be added to both test targets: When the tests are run by pressing Command + U or by navigating to Product | Test, the results of the test will be displayed. Changing either the implementation or the expected test result will demonstrate whether the test is being executed correctly. Always check whether a failing test causes the build to fail; this will confirm that the test is actually being run. For example, in the GitHubRepositoryTest class, modify the URL to remove https from the front and check whether a test failure is shown. There is nothing more useless than a correctly implemented test that never runs. Protocols in Swift A protocol is similar to an interface in other languages; it is a named type that has method signatures but no method implementations. Classes can implement zero or more protocols; when they do, they are said to adopt or conform to the protocol. A protocol may have a number of methods that are either required (the default) or optional (marked with the optional keyword). Optional protocol methods are only supported when the protocol is marked with the @objc attribute. This declares that the class will be backed by an NSObject class for interoperability with Objective-C. Pure Swift protocols cannot have optional methods. The syntax to define a protocol looks similar to the following: protocol GitHubDetails {   func detailsURL() -> String   // protocol needs @objc if using optional protocols   // optional doNotNeedToImplement() } Protocols cannot have functions with default arguments. Protocols can be used with the struct, class, and enum types unless the @objc class attribute is used; in which case, they can only be used against Objective-C classes or enums. Classes conform to protocols by listing the protocol names after the class name, similar to a superclass. When a class has both a superclass and one or more protocols, the superclass must be listed first. class GitHubRepository: GitHubDetails {   func detailsURL() -> String {     // implementation as before   } } The GitHubDetails protocol can be used as a type in the same places as an existing Swift type, such as a variable type, method return type, or argument type. Protocols are widely used in Swift to allow callbacks from frameworks that would, otherwise, not know about specific callback handlers. If a superclass was required instead, then a single class cannot be used to implement multiple callbacks. Common protocols include UIApplicationDelegate, Printable, and Comparable. Enums in Swift The final concept to understand in Swift is enumeration, or enum for short. An enum is a closed set of values, such as North, East, South, and West, or Up, and Down. An enumeration is defined using the enum keyword, followed by a type name, and a block, which contains the case keywords followed by comma-separated values as follows: enum Suit {   case Clubs, Diamonds, Hearts // many on one line   case Spades // or each on separate lines } Unlike C, enumerated values do not have a specific type by default, so they cannot generally be converted to and from an integer value. Enumerations can be defined with raw values that allow conversion to and from integer values. Enum values are assigned to variables using the type name and the enum name: var suit:Suit = Suit.Clubs However, if the type of the expression is known, then the type prefix does not need to be explicitly specified; the following form is much more common in Swift code: var suit:Suit = .Clubs Raw values For the enum values that have specific meanings, it is possible to extend the enum from a different type, such as Int. These are known as raw values: enum Rank: Int {   case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten   case Jack, Queen, King, Ace } A raw value enum can be converted to and from its raw value with the rawValue property and the failable initializer Rank(rawValue:) as follows: Rank.Two.rawValue == 2 Rank(rawValue:14)! == .Ace The failable initializer returns an optional enum value, because the equivalent Rank may not exist. The expression Rank(rawValue:0) will return nil, for example. Associated values Enums can also have associated values, such as a value or case class in other languages. For example, a combination of a Suit and a Rank can be combined to form a Card: enum Card {   case Face(Rank, Suit)   case Joker } Instances can be created by passing values into an enum initializer: var aceOfSpades: Card = .Face(.Ace,.Spades) var twoOfHearts: Card = .Face(.Two,.Hearts) var theJoker: Card = .Joker The associated values of an enum instance cannot be extracted (as they can with properties of a struct), but the enum value can be accessed by pattern matching in a switch statement: var card = aceOfSpades // or theJoker or twoOfHearts ... switch card {   case .Face(let rank, let suit):     print("Got a face card (rank) of (suit)");   case .Joker:     print("Got the joker card") } The Swift compiler will require that the switch statement be exhaustive. As the enum only contains these two types, no default block is needed. If another enum value is added to Card in the future, the compiler will report an error in this switch statement. Creating a master-detail iOS application Having covered how classes, protocols, and enums are defined in Swift, a more complex master-detail application can be created. A master-detail application is a specific type of iOS application that initially presents a master table view, and when an individual element is selected, a secondary details view will show more information about the selected item. Using the Create a new Xcode project option from the welcome screen, or by navigating to File | New | Project… or by pressing Command + Shift + N, create a new project and select Master-Detail Application from the iOS Application category: In the subsequent dialog, enter appropriate values for the project, such as the name (MasterDetail), the organization identifier (typically based on the reverse DNS name), ensure that the Language dropdown reads Swift and that it is targeted for Universal devices: When the project is created, an Xcode window will open containing all the files that are created by the wizard itself, including the MasterDetail.app and MasterDetailTests.xctest products. The MasterDetail.app is a bundle that is executed by the simulator or a connected device, while the MasterDetailTests.xctest and MasterDetailsUITests.xctest products are used to execute unit tests for the application's code. The application can be launched by pressing the triangular play button on the top-left corner of Xcode or by pressing Command + R, which will run the application against the currently selected target. After a brief compile and build cycle, the iOS Simulator will open with a master page that contains an empty table, as shown in the following screenshot: The default MasterDetail application can be used to add items to the list by clicking on the add (+) button on the top-right corner of the screen. This will add a new timestamped entry to the list. When this item is clicked, the screen will switch to the details view, which, in this case, presents the time in the center of the screen: This kind of master-detail application is common in iOS applications for displaying a top-level list (such as a shopping list, a set of contacts, to-do notes, and so on) while allowing the user to tap to see the details. There are three main classes in the master-detail application: The AppDelegate class is defined in the AppDelegate.swift file, and it is responsible for starting the application and set up the initial state The MasterViewController class is defined in the MasterViewController.swift file, and it is used to manage the first (master) screen's content and interactions The DetailViewController class is defined in the DetailViewController.swift file, and it is used to manage the second (detail) screen's content In order to understand what the classes do in more detail, the next three sections will present each of them in turn. The code that is generated in this section was created from Xcode 7.0, so the templates might differ slightly if using a different version of Xcode. An exact copy of the corresponding code can be acquired from the Packt website or from this book's GitHub repository at https://github.com/alblue/com.packtpub.swift.essentials/. The AppDelegate class The AppDelegate class is the main entry point to the application. When a set of Swift source files are compiled, if the main.swift file exists, it is used as the entry point for the application by running that code. However, to simplify setting up an application for iOS, a @UIApplicationMain special attribute exists that will both synthesize the main method and set up the associated class as the application delegate. The AppDelegate class for iOS extends the UIResponder class, which is the parent of all the UI content on iOS. It also adopts two protocols, UIApplicationDelegate, and UISplitViewControllerDelegate, which are used to provide callbacks when certain events occur: @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate,    UISplitViewControllerDelegate {   var window: UIWindow?   ... } On OS X, the AppDelegate class will be a subclass of NSApplication and will adopt the NSApplicationDelegate protocol. The synthesized main function calls the UIApplicationMain method that reads the Info.plist file. If the UILaunchStoryboardName key exists and points to a suitable file (the LaunchScreen.xib interface file in this case), it will be shown as a splash screen before doing any further work. After the rest of the application has loaded, if the UIMainStoryboardFile key exists and points to a suitable file (the Main.storyboard file in this case), the storyboard is launched and the initial view controller is shown. The storyboard has references to the MasterViewController and DetailViewController classes. The window variable is assigned to the storyboard's window. The application:didFinishLaunchingWithOptions is called once the application has started. It is passed with a reference to the UIApplication instance and a dictionary of options that notifies how the application has been started: func application(  application: UIApplication,  didFinishLaunchingWithOptions launchOptions:   [NSObject: AnyObject]?) -> Bool {   // Override point for customization after application launch.   ... } In the sample MasterDetail application, the application:didFinishLaunchingWithOptions method acquires a reference to the splitViewController from the explicitly unwrapped optional window, and the AppDelegate is set as its delegate: let splitViewController =  self.window!.rootViewController as! UISplitViewController splitViewController.delegate = self The … as! UISplitViewController syntax performs a type cast so that the generic rootViewController can be assigned to the more specific type; in this case, UISplitViewController. An alternative version as? provides a runtime checked cast, and it returns an optional value that either contains the value with the correctly casted type or nil otherwise. The difference with as! is a runtime error will occur if the item is not of the correct type. Finally, a navigationController is acquired from the splitViewController, which stores an array of viewControllers. This allows the DetailView to display a button on the left-hand side to expand the details view if necessary: let navigationController = splitViewController.viewController  [splitViewController.viewControllers.count-1]  as! UINavigationController navigationController.topViewController  .navigationItem.leftBarButtonItem =  splitViewController.displayModeButtonItem() The only difference this makes is when running on a wide-screen device, such as an iPhone 6 Plus or an iPad, where the views are displayed side-by-side in landscape mode. This is a new feature in iOS 8 applications. Otherwise, when the device is in portrait mode, it will be rendered as a standard back button: The method concludes with return true to let the OS know that the application has opened successfully. The MasterViewController class The MasterViewController class is responsible for coordinating the data that is shown on the first screen (when the device is in portrait orientation) or the left-half of the screen (when a large device is in landscape orientation). This is rendered with a UITableView, and data is coordinated through the parent UITableViewController class: class MasterViewController: UITableViewController {   var detailViewcontroller: DetailViewController? = nil   var objects = [AnyObject]()   override func viewDidLoad() {…}   func insertNewObject(sender: AnyObject) {…}   … } The viewDidLoad method is used to set up or initialize the view after it has loaded. In this case, a UIBarButtonItem is created so that the user can add new entries to the table. The UIBarButtonItem takes a @selector in Objective-C, and in Swift is treated as a string literal convertible (so that "insertNewObject:" will result in a call to the insertNewObject method). Once created, the button is added to the navigation on the right-hand side, using the standard .Add type which will be rendered as a + sign on the screen: override func viewDidLoad() {   super.viewDidLoad()   self.navigationItem.leftBarButtonItem = self.editButtonItem()   let addButton = UIBarButtonItem(     barButtonSystemItem: .Add, target: self,     action: "insertNewObject:")   self.navigationItem.rightBarButtonItem = addButton   if let split = self.splitViewController {     let controllers = split.viewControllers     self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController } The objects are NSDate values, and are stored inside the class as an Array of AnyObject elements. The insertNewObject method is called when the + button is pressed, and it creates a new NSDate instance which is then inserted into the array. The sender event is passed as an argument of the AnyObject type, which will be a reference to the UIBarButtonItem (although it is not needed or used here): func insertNewObject(sender: AnyObject) {   objects.insertObject(NSDate.date(), atIndex: 0)   let indexPath = NSIndexPath(forRow: 0, inSection: 0)   self.tableView.insertRowsAtIndexPaths(    [indexPath], withRowAnimation: .Automatic) } The UIBarButtonItem class was created before blocks were available on iOS devices, so it uses the older Objective-C @selector mechanism. A future release of iOS may provide an alternative that takes a block, in which case Swift functions can be passed instead. The parent class contains a reference to the tableView, which is automatically created by the storyboard. When an item is inserted, the tableView is notified that a new object is available. Standard UITableViewController methods are used to access the data from the array: override func numberOfSectionsInTableView(  tableView: UITableView) -> Int {   return 1 } override func tableView(tableView: UITableView,  numberOfRowsInSection section: Int) -> Int {   return objects.count } override func tableView(tableView: UITableView,  cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{   let cell = tableView.dequeueReusableCellWithIdentifier(    "Cell", forIndexPath: indexPath)   let object = objects[indexPath.row] as! NSDate   cell.textLabel!.text = object.description   return cell } override func tableView(tableView: UITableView,  canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {   return true } The numberOfSectionsInTableView function returns 1 in this case, but a tableView can have multiple sections; for example, to permit a contacts application having a different section for A, B, C through Z. The numberOfRowsInSection method returns the number of elements in each section; in this case, as there is only one section, the number of objects in the array. The reason why each method is called tableView and takes a tableView argument is a result of the Objective-C heritage of UIKit. The Objective-C convention combined the method name as the first named argument, so the original method was [delegate tableView:UITableView, numberOfRowsInSection:NSInteger]. As a result, the name of the first argument is reused as the name of the method in Swift. The cellForRowAtIndexPath method is expected to return UITableViewCell for an object. In this case, a cell is acquired from the tableView using the dequeueReusableCellWithIdentifier method (which caches cells as they go off screen to save object instantiation), and then the textLabel is populated with the object's description (which is a String representation of the object; in this case, the date). This is enough to display elements in the table, but in order to permit editing (or just removal, as in the sample application), there are some additional protocol methods that are required: override func tableView(tableView: UITableView,  canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {   return true } override func tableView(tableView: UITableView,  commitEditingStyle editingStyle: UITableViewCellEditingStyle,  forRowAtIndexPath indexPath: NSIndexPath) {   if editingStyle == .Delete {     objects.removeObjectAtIndex(indexPath.row)     tableView.deleteRowsAtIndexPaths([indexPath],      withRowAnimation: .Fade)   } } The canEditRowAtIndexPath method returns true if the row is editable; if all the rows can be edited, then this will return true for all the values. The commitEditingStyle method takes a table, a path, and a style, which is an enumeration that indicates which operation occurred. In this case, UITableViewCellEditingStyle.Delete is passed in order to delete the item from both the underlying object array and also from the tableView. (The enumeration can be abbreviated to .Delete because the type of editingStyle is known to be UITableViewCellEditingStyle.) The DetailViewController class The detail view is shown when an element is selected in the MasterViewController. The transition is managed by the storyboard controller; the views are connected with a segue (pronounced seg-way; the product of the same name based it on the word segue which is derived from the Italian word for follows). To pass the selected item between controllers, a property exists in the DetailViewController class called detailItem. When the value is changed, additional code is run, which is implemented in a didSet property notification: class DetailViewController: UIViewController {   var detailItem: AnyObject? {     didSet {       self.configureView()     }   }   … } When DetailViewController has the detailItem set, the configureView method will be invoked. The didSet body is run after the value has been changed, but before the setter returns to the caller. This is triggered by the segue in the MasterViewController: class MasterViewController: UIViewController {   …   override func prepareForSegue(    segue: UIStoryboardSegue, sender: AnyObject?) {     super.prepareForSegue(segue, sender: sender)     if segue.identifier == "showDetail" {       if let indexPath =        self.tableView.indexPathForSelectedRow() {         let object = objects[indexPath.row] as! NSDate         let controller = (segue.destinationViewController          as! UINavigationController)          .topViewController as! DetailViewController         controller.detailItem = object         controller.navigationItem.leftBarButtonItem =          self.splitViewController?.displayModeButtonItem()         controller.navigationItem.leftItemsSupplementBackButton =          true       }     }   } } The prepareForSegue method is called when the user selects an item in the table. In this case, it grabs the selected row index from the table and uses this to acquire the selected date object. The navigation controller hierarchy is searched to acquire the DetailViewController, and once this has been obtained, the selected value is set with controller.detailItem = object, which triggers the update. The label is ultimately displayed in the DetailViewController through the configureView method, which stamps the description of the object onto the label in the center: class DetailViewController {   ...   @IBOutlet weak var detailDescriptionLabel: UILabel!   function configureView() {     if let detail: AnyObject = self.detailItem {       if let label = self.detailDescriptionLabel {         label.text = detail.description       }     }   } } The configureView method is called both when the detailItem is changed and when the view is loaded for the first time. If the detailItem has not been set, then this has no effect. The implementation introduces some new concepts, which are worth highlighting: The @IBOutlet attribute indicates that the property will be exposed in interface builder and can be wired up to the object instance. The weak attribute indicates that the property will not store a strong reference to the object; in other words, the detail view will not own the object but merely reference it. Generally, all @IBOutlet references should be declared as weak to avoid cyclic dependency references. The type is defined as UILabel! which is an implicitly unwrapped optional. When accessed, it performs an explicit unwrapping of the optional value; otherwise the @IBOutlet will be wired up as a UILabel? optional type. Implicitly unwrapped optional types are used when the variable is known to never be nil at runtime, which is usually the case for the @IBOutlet references. Generally, all @IBOutlet references should be implicitly unwrapped optionals. Summary In this article we saw two sample iOS applications; one in which the UI was created programmatically, and another in which the UI was loaded from a storyboard. Together with an overview of classes, protocols, and enums, and an explanation of how iOS applications start, this article gives a springboard to understand the Xcode templates that are frequently used to start new projects. To learn more about Swift 2, you can refer the following books published by Packt Publishing (https://www.packtpub.com/): Swift 2 Blueprints (https://www.packtpub.com/application-development/swift-2-blueprints) Mastering Swift 2 (https://www.packtpub.com/application-development/mastering-swift-2) Swift 2 Design Patterns (https://www.packtpub.com/application-development/swift-2-design-patterns) Resources for Article:   Further resources on this subject: Your First Swift App [article] C-Quence – A Memory Game [article] Exploring Swift [article]
Read more
  • 0
  • 0
  • 8631
article-image-introduction-microsoft-azure-cloud-services
Packt
04 Jun 2015
10 min read
Save for later

Introduction to Microsoft Azure Cloud Services

Packt
04 Jun 2015
10 min read
In this article by Gethyn Ellis, author of the book Microsoft Azure IaaS Essentials, we will understand cloud computing and the various services offered by it. (For more resources related to this topic, see here.) Understanding cloud computing What do we mean when we talk about cloud from an information technology perspective? People mention cloud services; where do we get the services from? What services are offered? The Wikipedia definition of cloud computing is as follows: "Cloud computing is a computing term or metaphor that evolved in the late 1990s, based on utility and consumption of computer resources. Cloud computing involves application systems which are executed within the cloud and operated through internet enabled devices. Purely cloud computing does not rely on the use of cloud storage as it will be removed upon users download action. Clouds can be classified as public, private and [hybrid cloud|hybrid]." If you have worked with virtualization, then the concept of cloud is not completely alien to you. With virtualization, you can group a bunch of powerful hardware together, using a hypervisor. A hypervisor is a kind of software, operating system, or firmware that allows you to run virtual machines. Some of the popular Hypervisors on the market are VMware ESX or Microsoft's Hyper-V. Then, you can use this powerful hardware to run a set of virtual servers or guests. The guests share the resources of the host in order to execute and provide the services and computing resources of your IT department. The IT department takes care of everything from maintaining the hypervisor hosts to managing and maintaining the virtual servers and guests. The internal IT department does all the work. This is sometimes termed as a private cloud. Third-party suppliers, such as Microsoft, VMware, and Amazon, have a public cloud offering. With a public cloud, some computing services are provided to you on the Internet, and you can pay for what you use, which is like a utility bill. For example, let's take the utilities you use at home. This model can be really useful for start-up business that might not have an accurate demand forecast for their services, or the demand may change very quickly. Cloud computing can also be very useful for established businesses, who would like to make use of the elastic billing model. The more services you consume, the more you pay when you get billed at the end of the month. There are various types of public cloud offerings and services from a number of different providers. The TechNet top ten cloud providers are as follows: VMware Microsoft Bluelock Citrix Joyent Terrmark Salesforce.com Century Link RackSpace Amazon Web Services It is interesting to read that in 2013, Microsoft was only listed ninth in the list. With a new CEO, Microsoft has taken a new direction and put its Azure cloud offering at the heart of the business model. To quote one TechNet 2014 attendee: "TechNet this year was all about Azure, even the on premises stuff was built on the Azure model" With a different direction, it seems pretty clear that Microsoft is investing heavily in its cloud offering, and this will be further enhanced with further investment. This will allow a hybrid cloud environment, a combination of on-premises and public cloud, to be combined to offer organizations that ultimate flexibility when it comes to consuming IT resources. Services offered The term cloud is used to describe a variety of service offerings from multiple providers. You could argue, in fact, that the term cloud doesn't actually mean anything specific in terms of the service that you're consuming. It is, in fact, just a term that means you are consuming an IT service from a provider. Be it an internal IT department in the form of a private cloud or a public offering from some cloud provider, a public cloud, or it could be some combination of both in the form of a hybrid cloud. So, then what are the services that cloud providers offer? Virtualization and on-premises technology Most business even in today's cloudy environment has some on-premises technology. Until virtualization became popular and widely deployed several years ago, it was very common to have a one-to-one relationship between a physical hardware server with its own physical resources, such as CPU, RAM, storage, and the operating system installed on the physical server. It became clear that in this type of environment, you would need a lot of physical servers in your data center. An expanding and sometimes, a sprawling environment brings its own set of problems. The servers need cooling and heat management as well as a power source, and all the hardware and software needs to be maintained. Also, in terms of utilization, this model left lots of resources under-utilized: Virtualization changed this to some extent. With virtualization, you can create several guests or virtual servers that are configured to share the resources of the underlying host, each with their own operating system installed. It is possible to run both a Windows and Linux guest on the same physical host using virtualization. This allows you to maximize the resource utilization and allows your business to get a better return on investment on its hardware infrastructure: Virtualization is very much a precursor to cloud; many virtualized environments are sometimes called private clouds, so having an understanding of virtualization and how it works will give you a good grounding in some of the concepts of a cloud-based infrastructure. Software as a service (SaaS) SaaS is a subscription where you need to pay to use the software for the time that you're using it. You don't own any of the infrastructures, and you don't have to manage any of the servers or operating systems, you simply consume the software that you will be using. You can think of SaaS as like taking a taxi ride. When you take a taxi ride, you don't own the car, you don't need to maintain the car, and you don't even drive the car. You simply tell the taxi driver or his company when and where you want to travel somewhere, and they will take care of getting you there. The longer the trip, that is, the longer you use the taxi, the more you pay. An example of Microsoft's Software as a service would be the Azure SQL Database. The following diagram shows the cloud-based SQL database: Microsoft offers customers a SQL database that is fully hosted and maintained in Microsoft data centers, and the customer simply has to make use of the service and the database. So, we can compare this to having an on-premises database. To have an on-premises database, you need a Windows Server machine (physical or virtual) with the appropriate version of SQL Server installed. The server would need enough CPU, RAM, and storage to fulfill the needs of your database, and you need to manage and maintain the environment, applying various patches to the operating systems as they become available, installing, and testing various SQL Server service packs as they become available, and all the while, your application makes use of the database platform. With the SQL Azure database, you have no overhead, you simply need to connect to the Microsoft Azure portal and request a SQL database by following the wizard: Simply, give the database a name. In this case, it's called Helpdesk, select the service tier you want. In this example, I have chosen the Basic service tier. The service tier will define things, such as the resources available to your database, and impose limits, in terms of database size. With the Basic tier, you have a database size limit of 2 GB. You can specify the server that you want to create your database with, accept the defaults on the other settings, click on the check button, and the database gets created: It's really that simple. You will then pay for what you use in terms of database size and data access. In a later section, you will see how to set up a Microsoft Azure account. Platform as a service (PaaS) With PaaS, you rent the hardware, operating system, storage, and network from the public cloud service provider. PaaS is an offshoot of SaaS. Initially, SaaS didn't take off quickly, possibly because of the lack of control that IT departments and business thought they were going to suffer as a result of using the SaaS cloud offering. Going back to the transport analogy, you can compare PaaS to car rentals. When you rent a car, you don't need to make the car, you don't need to own the car, and you have no responsibility to maintain the car. You do, however, need to drive the car if you are going to get to your required destination. In PaaS terms, the developer and the system administrator have slightly more control over how the environment is set up and configured but still much of the work is taken care of by the cloud service provider. So, the hardware, operating system, and all the other components that run your application are managed and taken care of by the cloud provider, but you get a little more control over how things are configured. A geographically dispersed website would be a good example of an application offered on a PaaS offering. Infrastructure as a service (IaaS) With IaaS, you have much more control over the environment, and everything is customizable. Going with the transport analogy again, you can compare it to buying a car. The service provides you with the car upfront, and you are then responsible for using the car to ensure that it gets you from A to B. You are also responsible to fix the car if something goes wrong, and also ensure that the car is maintained by servicing it regularly, adding fuel, checking the tyre pressure, and so on. You have more control, but you also have more to do in terms of maintenance. Microsoft Azure has an offering. You can deploy a virtual machine, you can specify what OS you want, how much RAM you want the virtual machine to have, you can specify where the server will sit in terms of Microsoft data centers, and you can set up and configure recoverability and high availability for your Azure virtual machine: Hybrid environments With a hybrid environment, you get a combination of on-premises infrastructure and cloud services. It allows you to flexibly add resilience and high availability to your existing infrastructure. It's perfectly possible for the cloud to act as a disaster recovery site for your existing infrastructure. Microsoft Azure In order to work with the examples in this article, you need sign up for a Microsoft account. You can visit http://azure.microsoft.com/, and create an account all by yourself by completing the necessary form as follows: Here, you simply enter your details; you can use your e-mail address as your username. Enter the credentials specified. Return to the Azure website, and if you want to make use of the free trial, click on the free trial link. Currently, you get $125 worth of free Azure services. Once you have clicked on the free trial link, you will have to verify your details. You will also need to enter a credit card number and its details. Microsoft assures that you won't be charged during the free trial. Enter the appropriate details and click on Sign Up: Summary In this article, we looked at and discussed some of the terminology around the cloud. From the services offered to some of the specific features available in Microsoft Azure, you should be able to differentiate between a public and private cloud. You can also now differentiate between some of the public cloud offerings. Resources for Article: Further resources on this subject: Windows Azure Service Bus: Key Features [article] Digging into Windows Azure Diagnostics [article] Using the Windows Azure Platform PowerShell Cmdlets [article]
Read more
  • 0
  • 0
  • 8623

article-image-gpt-for-wealth-management-enhancing-customer-experience
Bhavishya Pandit
18 Sep 2023
10 min read
Save for later

GPT for Wealth Management: Enhancing Customer Experience

Bhavishya Pandit
18 Sep 2023
10 min read
Dive deeper into the world of AI innovation and stay ahead of the AI curve! Subscribe to our AI_Distilled newsletter for the latest insights and books. Don't miss out – sign up today!IntroductionIn the dynamic world of finance, technology continually pushes boundaries. Today, financial institutions seek to enhance customer experiences with a powerful tool: Generative Artificial Intelligence (AI). This cutting-edge technology is revolutionizing finance, reshaping customer interactions, and elevating satisfaction and personalization.Generative AI, known for creative output and data generation, is now making waves in finance. It offers unique opportunities to transform the customer experience. By harnessing Generative AI's capabilities, financial institutions gain valuable insights, provide hyper-personalized solutions, and align offerings with individual needs.This article explores Generative AI's impact on Wealth Management in finance. We uncover innovative applications, from personalized financial product recommendations to intuitive virtual assistants meeting customer needs. Additionally, we discuss the benefits, challenges, and ethical considerations of using Generative AI to enhance customer satisfaction.Customer Pain Points in Wealth ManagementIn the ever-evolving realm of finance, where wealth management and customer service intersect, customers often grapple with a host of challenges that can significantly impact their overall satisfaction. These obstacles stem from various sources and play a pivotal role in shaping customer loyalty. Here, we delve into some prevalent pain points experienced by customers in the finance sector, specifically in the context of wealth management and customer service:1. Lack of Personalization: Many clients seek financial advice and solutions tailored to their distinct goals and circumstances. Yet, conventional wealth management approaches often fall short of delivering this level of customization, leaving customers feeling disconnected and dissatisfied.2. Limited Accessibility: Accessibility issues can arise when clients encounter hurdles in accessing their financial data or communicating with their wealth managers and customer service representatives. Challenges in initiating contact, receiving timely responses, or navigating complex procedures can breed frustration and hinder the customer journey.3. Complex and Confusing Information: Financial matters are inherently intricate, and the use of complex jargon and technicalities can overwhelm customers. When information is not conveyed clearly and effectively, clients may find themselves bewildered, making it arduous to make well-informed decisions.4. Slow and Inefficient Processes: Lengthy processing times, excessive paperwork, and cumbersome procedures can be significant roadblocks in the customer experience. Clients demand streamlined, efficient processes that conserve time and effort, allowing them to manage their wealth seamlessly.5. Inadequate Communication and Transparency: Effective communication stands as the bedrock of trust and robust relationships. Clients place a premium on transparent, proactive communication from their wealth managers and customer service representatives. Inadequate communication or a lack of transparency concerning fees, performance updates, or policy changes can breed dissatisfaction and erode trust.6. Limited Innovation and Technology Adoption: Expectations are on the rise, with clients anticipating financial institutions to embrace technology and provide innovative solutions to enrich their financial management experience. A dearth of technological advancements, such as user-friendly digital platforms and interactive tools, can leave clients feeling underserved and disconnected.Mitigating these recurring customer pain points necessitates a customer-centric approach. This approach should encompass personalized services, streamlined processes, transparent communication, and a wholehearted embrace of innovative technologies. Through active engagement with these pain points, financial institutions can craft superior customer experiences, foster lasting relationships, and set themselves apart in an increasingly competitive landscape.How Generative AI can be used for Wealth Management?Let's dive right into the crux of the matter. Customers look to financial institutions not just for financial guidance but for personalized advice that aligns with their unique wealth aspirations. They place a high premium on financial expertise to help them navigate the path to their financial goals. Traditional wealth management has traditionally excelled in fostering strong client relationships, with each customer paired with a dedicated relationship manager who intimately understands their individual objectives.However, here's where things get interesting: the traditional methods of wealth management sometimes fall short of meeting the sky-high expectations for personalization. The limitations primarily stem from the scarcity of relationship managers, leading to challenges in scalability and sluggish communication. This communication bottleneck occasionally results in misunderstandings due to varying levels of subject comprehension. These roadblocks, unfortunately, can turn customers off, leaving them feeling adrift and dissatisfied.Enter Generative AI, poised to be the game-changer in wealth management. With its ability to sidestep scalability issues, Generative AI emerges as a promising solution. Picture this: every customer is equipped with an AGI-powered Chatbot capable of addressing their queries, understanding their goals, and furnishing personalized financial plans tailored to their specific requirements. It's a potential paradigm shift in customer service that holds the promise of seamless, individualized wealth management experiences.Now let us see the working of a use case. In this article, we will walk through an LLM-powered Chatbot that will answer user queries.Demonstrating a use-case: Context-based LLM-powered chatbot for Financial advice# Importing Dependenciesimport streamlit as st from streamlit_chat import message import openai import os# Mentioning API keyopenai.api_key = 'PASTE-YOUR-KEY' os.environ['OPENAI_API_KEY'] = "PASTE-YOUR-KEY"# Function to return response from GPTdef fun(prompt):    response = openai.ChatCompletion.create(                engine="engine_name",                messages = [                            {'role': 'user',                             'content': prompt}                          ],                temperature=0,                max_tokens=800,                top_p=0.95,                frequency_penalty=0,                presence_penalty=0,                stop=None)    response = response['choices'][0]['message']['content']    return response # Function that checks whether the question asked is out of context or not. Returns True or Falsedef context_check(prompt):    testing_query = f'''    Instructions:    Answer the questions only related to "{context_topics}".       Query:    Study the prompt "{prompt}" and tell whether the user directly or indirectly asking questions related to "{context_topics}".    Give a response only in "True" or "False".       Remember:    1. Do no generate any other output, example, code etc.     2. Answer should be 1 word only. True or False.    '''    response = fun(testing_query)    return response#Returns filtered response after context checkingdef generate_response(prompt):    for topic in context_topics:        if topic not in prompt:            is_contexual = 'False'    instructions = f'''         Instructions:        0. Assume yourself to be an expert in answering Financial queries        1. Answer questions only to the topics mention in: "{context_topics}" at all costs!        2. Be precise and crisp.        3. Answer in short.        '''    is_contexual = context_check(prompt)    if is_contexual == 'True':        prompt += instructions        response = fun(prompt)        return response    elif is_contexual == 'False':        return "Sorry the question asked doesn't follow the guidelines." # Gets the input text from streamlitdef get_text():    input_text = st.text_input("How may I help?", key='input')    return input_text with open('only_reply.txt', 'r') as f:        context_topics = f.read() context_topics = context_topics.split('\n')[:-1] # context_topics = ['Finance', 'Wealth Management', 'Investment', 'Wealth'] st.set_page_config(    page_title="FinBot",    page_icon="💰", )st.write("# Welcome to FinBot💰!") changes = ''' <style> [data-testid = "stAppViewContainer"]    {    background-image:url('https://i.ibb.co/qrrD42j/Screenshot-2023-09-15-at-5-41-25-PM.png');    background-size:cover;    }       div.esravye2 > iframe {        background-color: transparent;    } </style> ''' st.markdown(changes, unsafe_allow_html=True) if 'generated' not in st.session_state:    st.session_state['generated'] = [] if 'past' not in st.session_state:    st.session_state['past'] = []user_input = get_text() if user_input:    output = generate_response(user_input)    js_clear_input = """    <script>    const inputElement = document.querySelector('.stTextInput input');    inputElement.addEventListener('keydown', function(event) {        if (event.key === 'Enter') {            inputElement.value = '';        }    });    </script>    """# Display the JavaScript code st.markdown(js_clear_input, unsafe_allow_html=True)    st.experimental_set_query_params(text_input="")    st.session_state.past.append(user_input)    st.session_state.generated.append(output) if st.session_state['generated']:    for i in range(len(st.session_state['generated'])-1, -1, -1):        message(st.session_state['generated'][i], key=str(i))        message(st.session_state['past'][i], key="user_"+str(i), is_user=True)ScreenshotsBlocking Out of context questionContextual QuestionsConclusionIn conclusion, Generative AI stands as a game-changing force in the realm of wealth management. Its ability to provide personalized financial advice and solutions on a scale previously unattainable is reshaping the landscape of financial services. By leveraging the vast potential of Generative AI, financial institutions can navigate the complexities of modern finance with unparalleled precision.The anticipated impact is profound: clients receive tailored recommendations that align seamlessly with their unique financial goals, risk profiles, and the ever-evolving market dynamics. This, in turn, leads to improved investment outcomes, heightened client satisfaction, and a deepened sense of trust in financial institutions.As we march forward, the synergy between technology and human expertise will continue to define the future of wealth management. Generative AI, as a powerful ally, empowers advisors and clients alike to make informed decisions, optimize portfolios, and nurture enduring financial success. In this dynamic landscape, the marriage of cutting-edge technology and personalized financial guidance promises to usher in an era of unprecedented prosperity and financial well-being for all.Author BioBhavishya Pandit is a Data Scientist at Rakuten! He has been extensively exploring GPT to find use cases and build products that solve real-world problems.
Read more
  • 0
  • 0
  • 8622

article-image-backtrack-4-penetration-testing-methodologies
Packt
20 Apr 2011
14 min read
Save for later

BackTrack 4: Penetration testing methodologies

Packt
20 Apr 2011
14 min read
A robust penetration testing methodology needs a roadmap. This will provide practical ideas and proven practices which should be handled with great care in order to assess the system security correctly. Let's take a look at what this methodology looks like. It will help ensure you're using BackTrack effectively and that you're tests are thorough and reliable. Penetration testing can be carried out independently or as a part of an IT security risk management process that may be incorporated into a regular development lifecycle (for example, Microsoft SDLC). It is vital to notice that the security of a product not only depends on the factors relating to the IT environment, but also relies on product specific security's best practices. This involves implementation of appropriate security requirements, performing risk analysis, threat modeling, code reviews, and operational security measurement. PenTesting is considered to be the last and most aggressive form of security assessment handled by qualified professionals with or without prior knowledge of a system under examination. It can be used to assess all the IT infrastructure components including applications, network devices, operating systems, communication medium, physical security, and human psychology. The output of penetration testing usually contains a report which is divided into several sections addressing the weaknesses found in the current state of a system following their countermeasures and recommendations. Thus, the use of a methodological process provides extensive benefits to the pentester to understand and critically analyze the integrity of current defenses during each stage of the testing process. Different types of penetration testing Although there are different types of penetration testing, the two most general approaches that are widely accepted by the industry are Black-Box and White-Box. These approaches will be discussed in the following sections. Black-box testing The black-box approach is also known as external testing. While applying this approach, the security auditor will be assessing the network infrastructure from a remote location and will not be aware of any internal technologies deployed by the concerning organization. By employing the number of real world hacker techniques and following through organized test phases, it may reveal some known and unknown set of vulnerabilities which may otherwise exist on the network. An auditor dealing with black-box testing is also known as black-hat. It is important for an auditor to understand and classify these vulnerabilities according to their level of risk (low, medium, or high). The risk in general can be measured according to the threat imposed by the vulnerability and the financial loss that would have occurred following a successful penetration. An ideal penetration tester would undermine any possible information that could lead him to compromise his target. Once the test process is completed, a report is generated with all the necessary information regarding the target security assessment, categorizing and translating the identified risks into business context. White-box testing The white-box approach is also referred to as internal testing. An auditor involved in this kind of penetration testing process should be aware of all the internal and underlying technologies used by the target environment. Hence, it opens a wide gate for an auditor to view and critically evaluate the security vulnerabilities with minimum possible efforts. An auditor engaged with white-box testing is also known as white-hat. It does bring more value to the organization as compared to the blackbox approach in the sense that it will eliminate any internal security issues lying at the target infrastructure environment, thus, making it more tightened for malicious adversary to infiltrate from the outside. The number of steps involved in white-box testing is a bit more similar to that of black-box, except the use of the target scoping, information gathering, and identification phases can be excluded. Moreover, the white-box approach can easily be integrated into a regular development lifecycle to eradicate any possible security issues at its early stage before they get disclosed and exploited by intruders. The time and cost required to find and resolve the security vulnerabilities is comparably less than the black-box approach. The combination of both types of penetration testing provides a powerful insight for internal and external security viewpoints. This combination is known as Grey-Box testing, and the auditor engaged with gray-box testing is also known as grey-hat. The key benefit in devising and practicing a gray-box approach is a set of advantages posed by both approaches mentioned earlier. However, it does require an auditor with limited knowledge of an internal system to choose the best way to assess its overall security. On the other side, the external testing scenarios geared by the graybox approach are similar to that of the black-box approach itself, but can help in making better decisions and test choices because the auditor is informed and aware of the underlying technology. Vulnerability assessment versus penetration testing Since the exponential growth of an IT security industry, there are always an intensive number of diversities found in understanding and practicing the correct terminology for security assessment. This involves commercial grade companies and non-commercial organizations who always misinterpret the term while contracting for the specific type of security assessment. For this obvious reason, we decided to include a brief description on vulnerability assessment and differentiate its core features with penetration testing. Vulnerability assessment is a process for assessing the internal and external security controls by identifying the threats that pose serious exposure to the organizations assets. This technical infrastructure evaluation not only points the risks in the existing defenses but also recommends and prioritizes the remediation strategies. The internal vulnerability assessment provides an assurance for securing the internal systems, while the external vulnerability assessment demonstrates the security of the perimeter defenses. In both testing criteria, each asset on the network is rigorously tested against multiple attack vectors to identify unattended threats and quantify the reactive measures. Depending on the type of assessment being carried out, a unique set of testing process, tools, and techniques are followed to detect and identify vulnerabilities in the information assets in an automated fashion. This can be achieved by using an integrated vulnerability management platform that manages an up-to-date vulnerabilities database and is capable of testing different types of network devices while maintaining the integrity of configuration and change management. A key difference between vulnerability assessment and penetration testing is that penetration testing goes beyond the level of identifying vulnerabilities and hooks into the process of exploitation, privilege escalation, and maintaining access to the target system. On the other hand, vulnerability assessment provides a broad view of any existing flaws in the system without measuring the impact of these flaws to the system under consideration. Another major difference between both of these terms is that the penetration testing is considerably more intrusive than vulnerability assessment and aggressively applies all the technical methods to exploit the live production environment. However, the vulnerability assessment process carefully identifies and quantifies all the vulnerabilities in a non-invasive manner. This perception of an industry, while dealing with both of these assessment types, may confuse and overlap the terms interchangeably, which is absolutely wrong. A qualified consultant always makes an exception to workout the best type of assessment based on the client's business requirement rather than misleading them from one over the other. It is also a duty of the contracting party to look into the core details of the selected security assessment program before taking any final decision. Penetration testing is an expensive service when compared to vulnerability assessment. Security testing methodologies There have been various open source methodologies introduced to address security assessment needs. Using these assessment methodologies, one can easily pass the time-critical and challenging task of assessing the system security depending on its size and complexity. Some of these methodologies focus on the technical aspect of security testing, while others focus on managerial criteria, and very few address both sides. The basic idea behind formalizing these methodologies with your assessment is to execute different types of tests step-by-step in order to judge the security of a system accurately. Therefore, we have introduced four such well-known security assessment methodologies to provide an extended view of assessing the network and application security by highlighting their key features and benefits. These include: Open Source Security Testing Methodology Manual (OSSTMM) Information Systems Security Assessment Framework (ISSAF) Open Web Application Security Project (OWASP) Top Ten Web Application Security Consortium Threat Classification (WASC-TC) All of these testing frameworks and methodologies will assist the security professionals to choose the best strategy that could fit into their client's requirements and qualify the suitable testing prototype. The first two provide general guidelines and methods adhering security testing for almost any information assets. The last two mainly deal with the assessment of an application security domain. It is, however, important to note that the security in itself is an on-going process. Any minor change in the target environment can affect the whole process of security testing and may introduce errors in the final results. Thus, before complementing any of the above testing methods, the integrity of the target environment should be assured. Additionally, adapting any single methodology does not necessarily provide a complete picture of the risk assessment process. Hence, it is left up to the security auditor to select the best strategy that can address the target testing criteria and remains consistent with its network or application environment. There are many security testing methodologies which claim to be perfect in finding all security issues, but choosing the best one still requires a careful selection process under which one can determine the accountability, cost, and effectiveness of the assessment at optimum level. Thus, determining the right assessment strategy depends on several factors, including the technical details provided about the target environment, resource availability, PenTester's knowledge, business objectives, and regulatory concerns. From a business standpoint, investing blind capital and serving unwanted resources to a security testing process can put the whole business economy in danger. Open Source Security Testing Methodology Manual (OSSTMM) The OSSTMM is a recognized international standard for security testing and analysis and is being used by many organizations in their day-to-day assessment cycle. It is purely based on scientific method which assists in quantifying the operational security and its cost requirements in concern with the business objectives. From a technical perspective, its methodology is divided into four key groups, that is, Scope, Channel, Index, and Vector. The scope defines a process of collecting information on all assets operating in the target environment. A channel determines the type of communication and interaction with these assets, which can be physical, spectrum, and communication. All of these channels depict a unique set of security components that has to be tested and verified during the assessment period. These components comprise of physical security, human psychology, data networks, wireless communication medium, and telecommunication. The index is a method which is considerably useful while classifying these target assets corresponding to their particular identifications, such as, MAC Address, and IP Address. At the end, a vector concludes the direction by which an auditor can assess and analyze each functional asset. This whole process initiates a technical roadmap towards evaluating the target environment thoroughly and is known as Audit Scope. There are different forms of security testing which have been classified under OSSTMM methodology and their organization is presented within six standard security test types: Blind: The blind testing does not require any prior knowledge about the target system. But the target is informed before the execution of an audit scope. Ethical hacking and war gaming are examples of blind type testing. This kind of testing is also widely accepted because of its ethical vision of informing a target in advance. Double blind: In double blind testing, an auditor does not require any knowledge about the target system nor is the target informed before the test execution. Black-box auditing and penetration testing are examples of double blind testing. Most of the security assessments today are carried out using this strategy, thus, putting a real challenge for auditors to select the best of breed tools and techniques in order to achieve their required goal. Gray box: In gray box testing, an auditor holds limited knowledge about the target system and the target is also informed before the test is executed. Vulnerability assessment is one of the basic examples of gray box testing. Double gray box: The double gray box testing works in a similar way to gray box testing, except the time frame for an audit is defined and there are no channels and vectors being tested. White-box audit is an example of double gray box testing. Tandem: In tandem testing, the auditor holds minimum knowledge to assess the target system and the target is also notified in advance before the test is executed. It is fairly noted that the tandem testing is conducted thoroughly. Crystal box and in-house audit are examples of tandem testing. Reversal: In reversal testing, an auditor holds full knowledge about the target system and the target will never be informed of how and when the test will be conducted. Red-teaming is an example of reversal type testing. Which OSSTMM test type follows the rules of Penetration Testing? Double blind testing The technical assessment framework provided by OSSTMM is flexible and capable of deriving certain test cases which are logically divided into five security components of three consecutive channels, as mentioned previously. These test cases generally examine the target by assessing its access control security, process security, data controls, physical location, perimeter protection, security awareness level, trust level, fraud control protection, and many other procedures. The overall testing procedures focus on what has to be tested, how it should be tested, what tactics should be applied before, during and after the test, and how to interpret and correlate the final results. Capturing the current state of protection of a target system by using security metrics is considerably useful and invaluable. Thus, the OSSTMM methodology has introduced this terminology in the form of RAV (Risk Assessment Values). The basic function of RAV is to analyze the test results and compute the actual security value based on three factors, which are operational security, loss controls, and limitations. This final security value is known as RAV Score. By using RAV score an auditor can easily extract and define the milestones based on the current security posture to accomplish better protection. From a business perspective, RAV can optimize the amount of investment required on security and may help in the justification of better available solutions. Key features and benefits Practicing the OSSTMM methodology substantially reduces the occurrence of false negatives and false positives and provides accurate measurement for the security. Its framework is adaptable to many types of security tests, such as penetration testing, white-box audit, vulnerability assessment, and so forth. It ensures the assessment should be carried out thoroughly and that of the results can be aggregated into consistent, quantifiable, and reliable manner. The methodology itself follows a process of four individually connected phases, namely definition phase, information phase, regulatory phase, and controls test phase. Each of which obtain, assess, and verify the information regarding the target environment. Evaluating security metrics can be achieved using the RAV method. The RAV calculates the actual security value based on operational security, loss controls, and limitations. The given output known as the RAV score represents the current state of target security. Formalizing the assessment report using the Security Test Audit Report (STAR) template can be advantageous to management, as well as the technical team to review the testing objectives, risk assessment values, and the output from each test phase. The methodology is regularly updated with new trends of security testing, regulations, and ethical concerns. The OSSTMM process can easily be coordinated with industry regulations, business policy, and government legislations. Additionally, a certified audit can also be eligible for accreditation from ISECOM (Institute for Security and Open Methodologies) directly.
Read more
  • 0
  • 0
  • 8621
article-image-java-7-managing-files-and-directories
Packt
24 Feb 2012
12 min read
Save for later

Java 7: Managing Files and Directories

Packt
24 Feb 2012
12 min read
(For more resources on Java, see here.) Introduction It is often necessary to perform file manipulations, such as creating files, manipulating their attributes and contents, or removing them from the filesystem. The addition of the java.lang.object.Files class in Java 7 simplifies this process. This class relies heavily on the use of the new java.nio.file.Path interface. The methods of the class are all static in nature, and generally assign the actual file manipulation operations to the underlying filesystem. Many of the operations described in this chapter are atomic in nature, such as those used to create and delete files or directories. Atomic operations will either execute successfully to completion or fail and result in an effective cancellation of the operation. During execution, they are not interrupted from the standpoint of a filesystem. Other concurrent file operations will not impact the operation. To execute many of the examples in this chapter, the application needs to run as administrator. To run an application as administrator under Windows, right-click on the Command Prompt menu and choose Run as administrator. Then navigate to the appropriate directory and execute using the java.exe command. To run as administrator on a UNIX system, use the sudo command in a terminal window followed by the java command. Basic file management is covered in this chapter. The methods required for the creation of files and directories are covered in the Creating Files and Directories recipe. This recipe focuses on normal files. The creation of temporary files and directories is covered in the Managing temporary files and directories recipe and the creation of linked files is covered in the Managing symbolic links recipe. The options available for copying files and directories are found in the Controlling how a file is copied recipe. The techniques illustrated there provide a powerful way of dealing with file replication. Moving and deleting files and directories are covered in the Moving a file or directory and Deleting files and directories recipes, respectively. The Setting time-related attributes of a file or directory recipe illustrates how to assign time attributes to a file. Related to this effort are other attributes, such as file ownership and permissions. File ownership is addressed in the Managing file ownership recipe. File permissions are discussed in two recipes: Managing ACL file permissions and Managing POSIX file permissions. Creating files and directories The process of creating new files and directories is greatly simplified in Java 7. The methods implemented by the Files class are relatively intuitive and easy to incorporate into your code. In this recipe, we will cover how to create new files and directories using the createFile and createDirectory methods. Getting ready In our example, we are going to use several different methods to create a Path object that represents a file or directory. We will do the following: Create a Path object. Create a directory using the Files class' createDirectory method. Create a file using the Files class' createFile method. The FileSystem class' getPath method can be used to create a Path object, as can the Paths class' get method. The Paths class' static get method returns an instance of a Path based on a string sequence or a URI object. The FileSystem class' getPath method also returns a Path object, but only uses a string sequence to identify the file. How to do it... Create a console application with a main method. In the main method, add the following code that creates a Path object for the directory /home/test in the C directory. Within a try block, invoke the createDirectory method with your Path object as the parameter. This method will throw an IOException if the path is invalid. Next, create a Path object for the file newFile.txt using the createFile method on this Path object, again catching the IOException as follows: try{ Path testDirectoryPath = Paths.get("C:/home/test"); Path testDirectory = Files.createDirectory(testDirectoryPath); System.out.println("Directory created successfully!"); Path newFilePath = FileSystems.getDefault(). getPath("C:/home/test/newFile.txt"); Path testFile = Files.createFile(newFilePath); System.out.println("File created successfully!");}catch (IOException ex){ ex.printStackTrace();} Execute the program. Your output should appear as follows: Directory created successfully! File created successfully! Verify that the new file and directory exists in your filesystem. Next, add a catch block prior to the IOException after both methods, and catch a FileAlreadyExistsException: }catch (FileAlreadyExistsException a){System.out.println("File or directory already exists!");}catch (IOException ex){ ex.printStackTrace();} When you execute the program again, your output should appear as follows: File or directory already exists! How it works... The first Path object was created and then used by the createDirectory method to create a new directory. After the second Path object was created, the createFile method was used to create a file within the directory, which had just been created. It is important to note that the Path object used in the file creation could not be instantiated before the directory was created, because it would have referenced an invalid path. This would have resulted in an IOException. When the createDirectory method is invoked, the system is directed to check for the existence of the directory first, and if it does not exist, create it. The createFile method works in a similar fashion. The method fails if the file already exists. We saw this when we caught the FileAlreadyExistsException. Had we not caught that exception, an IOException would have been thrown. Either way, the existing file would not be overwritten. There's more... The createFile and createDirectory methods are atomic in nature. The createDirectories method is available to create directories, as discussed next. All three methods provide the option to pass file attribute parameters for more specific file creation. Using the createDirectories method to create a hierarchy of directories The createDirectories method is used to create a directory and potentially other intermediate directories. In this example, we build upon the previous directory structure by adding a subtest and a subsubtest directory to the test directory. Comment out the previous code that created the directory and file and add the following code sequence: Path directoriesPath = Paths. get("C:/home/test/subtest/subsubtest"); Path testDirectory = Files.createDirectories(directoriesPath); Verify that the operation succeeded by examining the resulting directory structure. See also Creating temporary files and directories is covered in the Managing temporary files and directories recipe. The creation of symbolic files is illustrated in the Managing symbolic links recipe. Controlling how a file is copied The process of copying files is also simplified in Java 7, and allows for control over the manner in which they are copied. The Files class' copy method supports this operation and is overloaded providing three techniques for copying those which differ by their source or destination. Getting ready In our example, we are going to create a new file and then copy it to another target file. This process involves: Creating a new file using the createFile method. Creating a path for the destination file. Copying the file using the copy method. How to do it... Create a console application with a main method. In the main method, add the following code sequence to create a new file. Specify two Path objects, one for your initial file and one for the location where it will be copied. Then add the copy method to copy that file to the destination location as follows: Path newFile = FileSystems.getDefault(). getPath("C:/home/docs/newFile.txt"); Path copiedFile = FileSystems.getDefault(). getPath("C:/home/docs/copiedFile.txt"); try{ Files.createFile(newFile); System.out.println("File created successfully!"); Files.copy(newFile, copiedFile); System.out.println("File copied successfully!");}catch (IOException e){ System.out.println("IO Exception.");} Execute the program. Your output should appear as follows: File created successfully! File copied successfully! When you execute the program again, your output should appear as follows: File copied successfully! How it works... The createFile method created your initial file, and the copy method copied that file to the location specified by the copiedFile variable. If you were to attempt to run that code sequence twice in a row, you would have encountered an IOException, because the copy method will not, by default, replace an existing file. The copy method is overloaded. The second form of the copy method used the java.lang.enum.StandardCopyOption enumeration value of REPLACE_EXISTING, which allowed the file to be replaced. The three enumeration values for StandardCopyOption are listed in the following table: Value Meaning ATOMIC_MOVE Perform the copy operation atomically COPY_ATTRIBUTES Copy the source file attributes to the destination file REPLACE_EXISTING Replace the existing file if it already exists Replace the copy method call in the previous example with the following: Files.copy(newFile, copiedFile, StandardCopyOption.REPLACE_EXISTING); When the code executes, the file should be replaced. Another example of the use of the copy options is found in the There's more... section of the Moving a file and directory recipe. There's more... If the source file and the destination file are the same, then the method completes, but no copy actually occurs. The copy method is not atomic in nature. There are two other overloaded copy methods. One copies a java.io.InputStream to a file and the other copies a file to a java.io.OutputStream. In this section, we will examine, in more depth, the processes of: Copying a symbolic link file Copying a directory Copying an input stream to a file Copying a file to an output stream Copying a symbolic link file When a symbolic link file is copied, the target of the symbolic link is copied. To illustrate this, create a symbolic link file called users.txt in the music directory to the users.txt file in the docs directory. Use the following code sequence to perform the copy operation: Path originalLinkedFile = FileSystems.getDefault(). getPath("C:/home/music/users.txt"); Path newLinkedFile = FileSystems.getDefault(). getPath("C:/home/music/users2.txt"); try{ Files.copy(originalLinkedFile, newLinkedFile); System.out.println("Symbolic link file copied successfully!");}catch (IOException e){ System.out.println("IO Exception.");} Execute the code. You should get the following output: Symbolic link file copied successfully! Examine the resulting music directory structure. The user2.txt file has been added and is not connected to either the linked file or the original target file. Modification of the user2.txt does not affect the contents of the other two files. Copying a directory When a directory is copied, an empty directory is created. The files in the original directory are not copied. The following code sequence illustrates this process: Path originalDirectory = FileSystems.getDefault(). getPath("C:/home/docs"); Path newDirectory = FileSystems.getDefault(). getPath("C:/home/tmp"); try{ Files.copy(originalDirectory, newDirectory); System.out.println("Directory copied successfully!");} catch (IOException e){ e.printStackTrace();} When this sequence is executed, you should get the following output: Directory copied successfully! Examine the tmp directory. It should be empty as any files in the source directory are not copied. Copying an input stream to a file The copy method has a convenient overloaded version that permits the creation of a new file based on the input from an InputStream. The first argument of this method differs from the original copy method, in that it is an instance of an InputStream. The following example uses this method to copy the jdk7.java.net website to a file: Path newFile = FileSystems.getDefault(). getPath("C:/home/docs/java7WebSite.html"); URI url = URI.create("http://jdk7.java.net/"); try (InputStream inputStream = url.toURL().openStream()) Files.copy(inputStream, newFile); System.out.println("Site copied successfully!");} catch (MalformedURLException ex){ ex.printStackTrace();}catch (IOException ex){ ex.printStackTrace();} When the code executes, you should get the following output: Site copied successfully! A java.lang.Object.URI object was created to represent the website. Using the URI object instead of a java.lang.Object.URL object immediately avoids having to create a separate try-catch block to handle the MalformedURLException exception. The URL class' openStream method returns an InputStream, which is used as the first parameter of the copy method. The copy method was then executed. The new file can now be opened with a browser or otherwise can be processed as needed. Notice that the method returns a long value representing the number of bytes written. Copying a file to an output stream The third overloaded version of the copy method will open a file and write its contents to an OutputStream. This can be useful when the content of a file needs to be copied to a non-file object such as a PipedOutputStream. It can also be useful when communicating to other threads or writing to an array of bytes, as illustrated here. In this example, the content of the users.txt file is copied to an instance of a ByteArrayOutputStream>. Its toByteArray method is then used to populate an array as follows: Path sourceFile = FileSystems.getDefault(). getPath("C:/home/docs/users.txt"); try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { Files.copy(sourceFile, outputStream); byte arr[] = outputStream.toByteArray(); System.out.println("The contents of " + sourceFile.getFileName()); for(byte data : arr) { System.out.print((char)data);} System.out.println();}catch (IOException ex) { ex.printStackTrace();} Execute this sequence. The output will depend on the contents of your file, but should be similar to the following: The contents of users.txt Bob Jennifer Sally Tom Ted Notice the use of the try-with-resources block that handles the opening and closing of the file. It is always a good idea to close the OutputStream, when the copy operation is complete or exceptions occur. The try-with-resources block handles this nicely. The method may block until the operation is complete in certain situations. Much of its behavior is implementation-specific. Also, the output stream may need to be flushed since it implements the Flushable interface. Notice that the method returns a long value representing the number of bytes written. See also See the Managing symbolic links recipe for more details on working with symbolic links.
Read more
  • 0
  • 0
  • 8621

article-image-android-user-interface-development-animating-widgets-and-layouts
Packt
23 Feb 2011
8 min read
Save for later

Android User Interface Development: Animating Widgets and Layouts

Packt
23 Feb 2011
8 min read
  Android User Interface Development: Beginner's Guide Quickly design and develop compelling user interfaces for your Android applications Leverage the Android platform's flexibility and power to design impactful user-interfaces Build compelling, user-friendly applications that will look great on any Android device Make your application stand out from the rest with styles and themes A practical Beginner's Guide to take you step-by-step through the process of developing user interfaces to get your applications noticed! Animations are an important element in the user interface design of a modern application. However, it's also easy to overuse animations in your designs. A general guideline for animation use in a non-game application is—only animate user interactions and notifications, and keep the duration short so that it doesn't impact the user's experience negatively. For a game, more animation is generally acceptable (or even expected). Layout animations and transitions provide useful status information to the user. When using a screen transition you tell your user what has just happened, or what is about to happen. Different transitions signify different events to your users, knowing what transition to use for each different activity will let your users know what kind of action is about to be taken. Layout animations are an important part of your user feedback, leaving them out or using the wrong one in the wrong place can leave your users irritated, or slightly confused ("change dazed"). Using the right animations will improve user experience, and can even speed up their use of the application by giving them brief cues as to what they are expected to do next. Using standard Android animations Any View or ViewGroup object in Android can have an animation attached to it. animations are generally defined as application resources in an XML file, and Android provides a few useful defaults in the android package. Android also includes several View classes which are designed specifically to handle animations. With these classes you will find that they have layout attributes which allow you to set a particular types of animations that will be used upon certain actions. However, animations are generally not specified in a layout file, instead they rely on the Java code to set and start Animation objects. The main reason why animations are not normally specified as part of the layout XML is very simple—when should they run? Many animations can be used as a response to user input, letting the user know what's happening. Most animations will in some way or the other be triggered by a user's action (unless they are there to serve as a notification). Thus you will need to specify both—which animation to run on a widget, and the signal about when the animation should run. The default Android animations will begin animating immediately, while other animation structures may have a scheduled delay before they start. Time for action – animating a news feed We'll start of by creating a selector Activity and a simple NewsFeedActivity. In a news feed, we'll animate the latest headlines "in and out" using a timer. For this example we'll be working with some of the default animations provided by Android and driving the process mainly through the layout resources. Create a new project to contain the animation examples from this article, with a main Activity named AnimationSelectionActivity: android create project -n AnimationExamples -p AnimationExamples -k com.packtpub.animations -a AnimationSelector -t 3 Open the res/layout/main.xml layout file in an editor or IDE. Clear out the default content of the layout resource. Declare a vertical LinearLayout consuming all the available screen space: <LinearLayout android_orientation="vertical" android_layout_width="fill_parent" android_layout_height="fill_parent"> Create a Button labeled News Feed to link to the first animation example: <Button android_id="@+id/news_feed" android_layout_width="fill_parent" android_layout_height="wrap_content" android_layout_marginBottom="10dip" android_text="News Feed"/> Create a new layout resource file named news.xml. Declare a vertical LinearLayout containing all of the available screen space: <LinearLayout android_orientation="vertical" android_layout_width="fill_parent" android_layout_height="fill_parent">" Add a TextSwitcher object to the LinearLayout, specifying the "in" and "out" animations to the default "slide" animations: <TextSwitcher android_id="@+id/news_feed" android_inAnimation="@android:anim/slide_in_left" android_outAnimation="@android:anim/slide_out_right" android_layout_width="fill_parent" android_layout_height="wrap_content" android_text=""/> Open the res/values/strings.xml file in an editor or IDE. Declare a string-array named headlines with elements for some mock news headlines: <string-array name="headlines"> <item>Pwnies found to inhabit Mars</item> <item>Geeks invent "atoms"</item> <item>Politician found not lying!</item> <!-- add some more items here if you like --> </string-array> In the generated root package, declare a new Java source file named NewsFeedActivity.java. Register the NewsFeedActivity class in your AndroidManifest.xml file: <activity android_name=".NewsFeedActivity" android_label="News Feed" /> The new class should extend the Activity class and implement Runnable: public class NewsFeedActivity extends Activity implements Runnable { Declare a Handler to be used as a timing structure for changing the headlines: private final Handler handler = new Handler(); We need a reference to the TextSwitcher object: private TextSwitcher newsFeed; Declare a string-array to hold the mock headlines you added to the strings.xml file: private String[] headlines; You'll also need to keep track of which headline is currently being displayed: private int headlineIndex; Override the onCreate method: protected void onCreate(final Bundle savedInstanceState) { Invoke the onCreate method of Activity: super.onCreate(savedInstanceState); Set the content view to the news layout resource: setContentView(R.layout.news); Store a reference to the headline string-array from the strings.xml application resource file: headlines = getResources().getStringArray(R.array.headlines); Find the TextSwitcher widget and assign it to the field declared earlier: newsFeed = (TextSwitcher)findViewById(R.id.news_feed); Set the ViewFactory of the TextSwitcher to a new anonymous class that will create TextView objects when asked: newsFeed.setFactory(new ViewFactory() { public View makeView() { return new TextView(NewsFeedActivity.this); } }); Override the onStart method: protected void onStart() { Invoke the onStart method of the Activity class: super.onStart(); Reset the headlineIndex so that we start from the first headline: headlineIndex = 0; Post the NewsFeedActivity as a delayed action using the Handler: handler.postDelayed(this, 3000); Override the onStop method: protected void onStop() { Invoke the onStop method of the Activity class: super.onStop(); Remove any pending calls to the NewsFeedActivity: handler.removeCallbacks(this); Implement the run method which we'll use to swap to the next headline: public void run() { Open a try block to swap the headline inside. Use the TextSwitcher.setText method to swap to the next headline: newsFeed.setText(headlines[headlineIndex++]); If the headlineIndex is past the total number of headlines, reset the headlineIndex to zero: if(headlineIndex >= headlines.length) { headlineIndex = 0; }Animatng Widgets and Layouts Close the try block, and add a finally block. In the finally block, post the NewsFeedActivity back onto the Handler queue: finally { handler.postDelayed(this, 3000); } Open the auto generated AnimationSelector Java source in an editor or IDE. The AnimationSelector class needs to implement OnClickListener: public class AnimationSelector extends Activity implements OnClickListener { In the onCreate method, ensure that the content view is set to the main layout resource created earlier: setContentView(R.layout.main); Find the declared Button and set its OnClickListener to this: ((Button)findViewById(R.id.news_feed)). setOnClickListener(this); Declare the onClick method: public void onClick(final View view) { Use a switch to determine which View was clicked: switch(view.getId()) { If it's the news feed Button, then use the following case: case R.id.news_feed: Start the NewsFeedActivity using a new Intent: startActivity(new Intent(this, NewsFeedActivity.class)); Break from the switch statement, thus finishing the onClick method. What just happened? The TextSwitcher is an example of an animation utility View. In this case it's the perfect structure to swap between the news headlines, displaying one headline at a time and animating a transition between each of the texts. The TextSwitcher object creates two TextView objects (using the anonymous ViewFactory class). When you use the setText method, the TextSwitcher changes the text of the "of screen" TextView and animates a transition between the "on screen" TextView and the "of screen" TextView (with the new text content displayed). The TextSwitcher class requires that you specify two animation resources for it to work with, in order to create its transition effect: Animate text onto the screen Animate text of the screen In the previous case, we made use of the default slide_in_left and slide_out_right animations. Both of these are examples of translation-based animations due to the fact that they actually alter the "on screen" position of the TextView objects in order to create their effect.
Read more
  • 0
  • 0
  • 8618
Modal Close icon
Modal Close icon