Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
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

7019 Articles
article-image-gesture
Packt
25 Oct 2013
5 min read
Save for later

Gesture

Packt
25 Oct 2013
5 min read
(For more resources related to this topic, see here.) Gestures While there are ongoing arguments in the courts of America at the time of writing over who invented the likes of dragging images, it is without a doubt that a key feature of iOS is the ability to use gestures. To put it simply, when you tap the screen to start an app or select a part of an image to enlarge it or anything like that, you are using gestures. A gesture (in terms of iOS) is any touch interaction between the UI and the device. With iOS 6, there are six gestures the user has the ability to use. These gestures, along with brief explanations, have been listed in the following table: Class Name and type Gesture UIPanGesture Recognizer PanGesture; Continuous type Pan images or over-sized views by dragging across the screen UISwipeGesture Recognizer SwipeGesture; Continuous type Similar to panning, except it is a swipe UITapGesture Recognizer TapGesture; Discrete type Tap the screen a number of times (configurable) UILongPressGesture Recognizer LongPressGesture; Discrete type Hold the finger down on the screen UIPinchGesture Recognizer PinchGesture; Continuous type Zoom by pinching an area and moving your fingers in or out UIRotationGesture Recognizer RotationGesture; Continuous type Rotate by moving your fingers in opposite directions Gestures can be added by programming or via Xcode. The available gestures are listed in the following screenshot with the rest of the widgets on the right-hand side of the designer: To add a gesture, drag the gesture you want to use under the view on the View bar (shown in the following screenshot): Design the UI as you want and while pressing the Ctrl key, drag the gesture to what you want to recognize using the gesture. In my example, the object you want to recognize is anywhere on the screen. Once you have connected the gesture to what you want to recognize, you will see the configurable options of the gesture. The Taps field is the number of taps required before the Recognizer is triggered, and the Touches field is the number of points onscreen required to be touched for the Recognizer to be triggered. When you come to connect up the UI, the gesture must also be added. Gesture code When using Xcode, it is simple to code gestures. The class defined in the Xcode design for the tapping gesture is called tapGesture and is used in the following code: private int tapped = 0; public override void ViewDidLoad() { base.ViewDidLoad(); tapGesture.AddTarget(this, new Selector("screenTapped")); View.AddGestureRecognizer(tapGesture); } [Export("screenTapped")]public void SingleTap(UIGestureRecognizer s) { tapped++; lblCounter.Text = tapped.ToString(); } There is nothing really amazing to the code; it just displays how many times the screen has been tapped. The Selector method is called by the code when the tap has been seen. The method name doesn't make any difference as long as the Selector and Export names are the same. Types When the gesture types were originally described, they were given a type. The type reflects the number of messages sent to the Selector method. A discrete one generates a single message. A continuous one generates multiple messages, which requires the Selector method to be more complex. The complexity is added by the Selector method having to check the State of the gesture to decide on what to do with what message and whether it has been completed. Adding a gesture in code It is not a requirement that Xcode be used to add a gesture. To perform the same task in the following code as my preceding code did in Xcode is easy. The code will be as follows: UITapGestureRecognizer t'pGesture = new UITapGestureRecognizer() { NumberOfTapsRequired = 1 }; The rest of the code from AddTarget can then be used. Continuous types The following code, a Pinch Recognizer, shows a simple rescaling. There are a couple of other states that I'll explain after the code. The only difference in the designer code is that I have UIImageView instead of a label and a UIPinchGestureRecognizer class instead of a UITapGestureRecognizer class. public override void ViewDidLoad() { base.ViewDidLoad(); uiImageView.Image =UIImage.FromFile("graphics/image.jpg") Scale(new SizeF(160f, 160f); pinchGesture.AddTarget(this, new Selector("screenTapped")); uiImageView.AddGestureRecognizer(pinchGesture); } [Export("screenTapped")]public void SingleTap(UIGestureRecognizer s) { UIPinchGestureRecognizer pinch = (UIPinchGestureRecognizer)s; float scale = 0f; PointF location; switch(s.State) { case UIGestureRecognizerState.Began: Console.WriteLine("Pinch begun"); location = s.LocationInView(s.View); break; case UIGestureRecognizerState.Changed: Console.WriteLine("Pinch value changed"); scale = pinch.Scale; uiImageView.Image = UIImage FromFile("graphics/image.jpg") Scale(new SizeF(160f, 160f), scale); break; case UIGestureRecognizerState.Cancelled: Console.WriteLine("Pinch cancelled"); uiImageView.Image = UIImage FromFile("graphics/image.jpg") Scale(new SizeF(160f, 160f)); scale = 0f; break; case UIGestureRecognizerState.Recognized: Console.WriteLine("Pinch recognized"); break; } } Other UIGestureRecognizerState values The following table gives a list of other Recognizer states: State Description Notes Possible Default state; gesture hasn't been recognized Used by all gestures Failed Gesture failed No messages sent for this state Translation Direction of pan Used in the pan gesture Velocity Speed of pan Used in the pan gesture In addition to these, it should be noted that discrete types only use Possible and Recognized states. Summary Gestures certainly can add a lot to your apps. They can enable the user to speed around an image, move about a map, enlarge and reduce, as well as select areas of anything on a view. Their flexibility underpins why iOS is recognized as being an extremely versatile device for users to manipulate images, video, and anything else on-screen. Resources for Article: Further resources on this subject: Creating and configuring a basic mobile application [Article] So, what is XenMobile? [Article] Building HTML5 Pages from Scratch [Article]
Read more
  • 0
  • 0
  • 7402

article-image-advanced-system-management
Packt
25 Oct 2013
11 min read
Save for later

Advanced System Management

Packt
25 Oct 2013
11 min read
(For more resources related to this topic, see here.) Beyond backups Of course, backups are not the only issue with managing multiple, remote systems. In particular, managing such multiple configurations using a centralized application is often desirable. Configuration management One of the issues frequently faced by administrators is that of having multiple, remote systems all with similar software for the most part, but with minor differences in what is installed or running. Debian provides several packages that can help manage such an environment in a unified manner. Two of the more popular packages, both available in Debian, are FAI and Puppet. While we don't have the space to go into details, both applications are described briefly here. Fully Automated Installation Fully Automated Installation (FAI) focuses on managing Linux installations, and is developed using Debian, although it works with many different distributions, not just Debian. FAI uses a class concept for categorizing similar systems, and provides a good deal of flexibility and customization via hooks. FAI provides for unattended, automatic installation as well as tools for monitoring and updating groups of systems. FAI is frequently used for creating and maintaining clusters. More information is available at http://fai-project.org/. Puppet Probably the best known application for distributed management is Puppet, developed by Puppet Labs. Unlike FAI, only the Open Source edition is free, the Enterprise edition, which has many additional features, is not. Puppet does include support for environments other than Linux. The desired configuration is described in a custom, high-level definition language, and distributed to systems with installed clients. Unlike FAI, Puppet does not provide its own bare metal remote installation method, but does use existing methods (such as kickstart) to provide this function. A number of companies that make heavy use of distributed and clustered systems use Puppet to manage their environments. More information is available at http://puppetlabs.com/. Other packages There are other packages that can be used to manage a distributed environment, such as Chef and BCFG2. While simpler than Puppet or FAI, they support similar functions and have been used in some distributed and clustered environments. The use of FAI, Puppet, and others in cluster management warrants a brief look at clustering next, and what packages in Debian support clustering. Clusters A cluster is a group of systems that work together in such a way that the whole functions as a single unit. Such clusters can be loosely coupled or tightly coupled. A loosely coupled environment, each system is complete in itself, and can handle all of the tasks any of the other systems can handle. The environment provides mechanisms for redundancy, load sharing, and fail-over between systems, and is often called a High Availability (HA) cluster. In a tightly coupled environment, the systems involved are highly dependent on one another, often sharing memory and disk storage, and all work on the same task together. The environment provides mechanisms for data sharing, avoiding storage conflicts, keeping the systems in synchronization, and splitting up tasks appropriately. This design is often used in super-computing environments. Clustering is an advanced technique that involves more than just installing and configuring software. It also involves hardware integration, and systems and network design, and implementation. Along with the URLs mentioned below, a good text on the subject is Building Clustered Linux Systems, by Robert W. Lucke, Prentice Hall. Here we will only touch the very basics, along with what tools Debian provides. Let's take a brief look at each environment, and some of the tools used to create them. High Availability clusters Two primary functions are required to implement a high availability cluster: A way to handle load balancing and individual host fail-over. A way to synchronize storage so that all servers provide the same view of the data they serve. Debian includes meta packages that bring together software from the Linux High Availability project, including cluster-agents and resource-agents, two of the higher-level meta packages. These packages install various agents that are useful in coordinating and managing load balancing and fail-over. In some cases, a master server is designated to distribute the processing load among other servers. Data synchronization is handled by using shared storage and any of the filesystems that provide for multiple accesses and shared files, such as NFS or AFS. High Availability clusters generally use standard software, along with software that is readily available to manage the dynamics of such environments. Beowulf clusters In addition to the considerations for High Availability clusters, more tightly coupled environments such as Beowulf clusters also require an infrastructure to manage and distribute computing tasks. There are several web pages devoted to creating a Beowulf cluster using Debian as well as packages that aid in creating such a cluster. One such page is https://wiki.debian.org/StartaBeowulf, a Debian Wiki page on Beowulf basics. The manual for FAI also has a section on creating a Beowulf cluster. Books are available as well. Debian provides several packages that are helpful in building such a cluster, such as the OpenMPI libraries for message passing, and various utilities that run commands on multiple systems, such as those in the kadif package. There are even projects that have released scripts and live CDs that allow you to set up a cluster quickly (one such project is the PelicanHPC project, developed for Debian Lenny, hosted at http://www.pelicanhpc.org/. This type of cluster is not something that you can set up and go. Beowulf and other tightly coupled clusters are intended for highly parallel computing, and the programs that do the actual computing must be designed specifically for such an environment. That said, some packages for specific parallel computations do exist in Debian, such as nwchem, which provides several applications for computational chemistry that take advantage of parallelism. Common tools Some common components of clusters have already been mentioned, such as the OpenMPI libraries. Aside from the meta-packages already mentioned, the redhat-cluster suite of tools is available in Debian, as well as many useful libraries, scheduling tools, and failover tools such as booth. All of these can be found using apt-cache or Synaptic by searching for "cluster". Webmin Many administrators will never have to administer a cluster, and many won't be responsible for a large number of systems requiring central backup solutions. However, even administering a single system using command line tools and text editors can be a chore. Even clusters sometimes require administrative tasks on individual systems. Fortunately, there is an application that can ease many administrative tasks, is easy to use, and can handle many aspects of Linux administration. It is called Webmin. Up until Debian Sarge, Webmin was a part of Debian distributions. However, the Debian developer in charge of packaging it had difficulty keeping up with the frequent releases, and it was eventually dropped from Debian. However, the upstream Webmin developers maintain current packages that install cleanly. Some users have reported issues because Webmin does not always handle configuration files exactly as Debian intends, but it most certainly attempts to handle them in a compatible manner, and while some users have experienced problems with upgrades, many administrators are quite happy with Webmin. As long as you are willing to deal with conflicts during upgrades, or restrict use of modules that have major configuration impacts, you will find Webmin quite useful. Installing Webmin Webmin may be installed by adding the following lines to your apt sources file: deb http://download.webmin.com/download/repository sarge contrib deb http://webmin.mirror.somersettechsolutions.co.uk/repository sarge contrib Usually, this is added to a separate webmin.list file in /etc/apt/sources.list.d. The use of 'sarge' for the release name in the configuration is not a mistake. Since Webmin was dropped after the Sarge release (Debian 3.1), the developers update the repository as it is and haven't bothered changing it to keep up with the Debian code names. However, the versions available in the repository are compatible with any Debian release since 3.1. After updating your cache file, Webmin can be installed and maintained using apt-get, aptitude, or Synaptic. Also, if you request a Webmin upgrade from within Webmin itself on a Debian system, it will use the proper Debian package to upgrade. Using Webmin Webmin runs in the background, and provides an HTTP or HTTPS server on localhost port 10,000. You can use any web browser to connect to http://localhost:10000/ to access Webmin. Upon first installation, only the root user or those in a group allowed to use sudo to access the root account, may log in but Webmin users can be managed separately or in conjunction with local users. Webmin provides extensive and easy to understand menus and icons for various configuration tasks. Webmin is also highly modular and extensible, and an extensive list of standard modules is included with the base package. It is not possible to cover Webmin as fully here as it deserves, but a short list of some of its capabilities includes: Configuration of Webmin itself (the server, users, modules, and security) Local system user and password management Filesystem management Bootup and service management CRON job management Software updates Basic filesystem backups Authentication and security configuration APACHE, DNS, SSH, and FTP (if you're using ProFTP) configuration User mail management Qmail or sendmail configuration Network and Firewall configuration and management Bandwidth monitoring Printer management There are even modules that apply to clusters. Also, Webmin can search and allow access to other Webmin servers on the local network or you can define remote servers manually. This allows a central Webmin server, installed on a particular system, to be the gateway to all of the other servers in your environment, essentially providing a single point of access to manage all Webmin enabled servers. Webmin and Debian Webmin understands the configuration file layout of many distributions. The main problem is when a particular module does not handle certain types of configuration in the way the Debian developers prefer, which can make package upgrades somewhat difficult. This can be handled in a couple of ways. Most modules provide a means to edit configuration files directly, so if you have read the Debian documentation you can modify the configuration appropriately to use Debian specific configuration techniques. Or, you may choose to allow Webmin to modify files as it sees fit, and handle any conflicts manually when you upgrade the software involved. Finally, you can avoid those modules involved with specific software that are more likely to cause problems. One such module is Apache, which doesn't use links from sites-enabled to sites-available. Rather, it configures directly in the sites-enabled directory. Some administrators create the configuration in Webmin, and then move and link the files. Others prefer to manually configure Apache outside of Webmin. Webmin modules are constantly changing, and some actually recognize the Debian file layouts well, so it is not possible to give a comprehensive list of modules to avoid at this time. Best practice when using Webmin is to read the documentation and check the configuration files for specific software prior to using Webmin. Then, after configuring with Webmin, check the files again to determine whether changes may be required to work within the particular package's Debian configuration framework. Based upon this, you can decide whether to continue to configure using Webmin or switch back to manual configuration of that particular software. Webmin security Security is always a concern when remote access to a system is involved. Webmin handles this by requiring authentication and providing for detailed access restrictions that provide a layer of control beyond the firewall. Webmin users can be defined separately, or certain local users can be designated. Access to the various modules in Webmin can be restricted to certain users or groups of users, and detailed logs of Webmin actions are kept. Usermin In addition to Webmin, there is a server called Usermin which may be installed from the same repository as Webmin. It allows individual users to perform a number of functions more easily, such as changing their password, accessing their files, read and manage their email, and managing some aspects of their user profile. It is also modular and has the same security features as Webmin. Summary Several powerful and flexible central backup solutions exist that help manage backups for multiple remote servers and sites. Debian provides packages that assist in building High Availability and Beowulf style multiprocessing clusters as well. And, whether you are involved in managing clusters or not, or even a single system, Webmin can ease an administrator's tasks. Resources for Article: Further resources on this subject: Customizing a Linux kernel [Article] Microsoft SharePoint 2010 Administration: Farm Governance [Article] Testing Workflows for Microsoft Dynamics AX 2009 Administration [Article]
Read more
  • 0
  • 0
  • 5659

article-image-lets-breakdown-numbers
Packt
24 Oct 2013
8 min read
Save for later

Let's Breakdown the Numbers

Packt
24 Oct 2013
8 min read
(For more resources related to this topic, see here.) John Kirkland is an awesome "accidental" SQL Server DBA for Red Speed Bicycle LLC—a growing bicycle startup based in the United States. The company distributes bikes, bicycle parts, and accessories to various distribution points around the world. To say that they are performing well financially is an understatement. They are booming! They've been expanding their business to Canada, Australia, France, and the United Kingdom in the last three years. The company has upgraded their SQL Server 2000 database recently to the latest version of SQL Server 2012. Linda, from the Finance Group, asked John if they can migrate their Microsoft Access Reports into the SQL Server 2012 Reporting Services. John installed SSRS 2012 in a native mode. He decided to build the reports from the ground up so that the report development process would not interrupt the operation in the Finance Group. There is only one caveat; John has never authored any reports in SQL Server Reporting Services (SSRS) before. Let's give John a hand and help him build his reports from the ground up. Then, we'll see more of his SSRS adventures as we follow his journey throughout this article. Here's the first report requirement for John: a simple table that shows all the sales transactions in their database. Linda wants to see a report with the following data: Date Sales Order ID Category Subcategory Product Name Unit Price Quantity Line Total We will build our report, and all succeeding reports in this article, using the SQL Server Data Tools (SSDT). SSDT is Visual Studio shell which is an integrated environment used to build SQL Server database objects. You can install SSDT from the SQL Server installation media. In June 2013, Microsoft released SQL Server Data Tools-Business Intelligence (SSDTBI). SSDTBI is a component that contains templates for SQL Server Analysis Services (SSAS), SQL Server Integration Services (SSIS), and SQL Server Reporting Services (SSRS) for Visual Studio 2012. SSDTBI replaced Business Intelligence Development Studio (BIDS) from the previous versions of SQL Server. You have two options in creating your SSRS reports: SSDT or Visual Studio 2012. If you use Visual Studio, you have to install the SSDTBI templates. Let's create a new solution and name it SSRS2012Blueprints. For the following exercises, we're using SSRS 2012 in native mode. Also, make a note that we're using the AdventureWorks2012 Sample database all throughout this article unless otherwise indicated. You can download the sample database from CodePlex. Here's the link: http://msftdbprodsamples.codeplex.com/releases/view/55330. Defining a data source for the project Now, let's define a shared data source and shared dataset for the first report. A shared dataset and data source can be shared among the reports within the project: Right-click on the Shared Data Sources folder under the SSRS2012Bueprints solution in the Solution Explorer window, as shown in the following illustration. If the Solution Explorer window is not visible, access it by navigating to Menu | View | Solution Explorer, or press Ctrl + Alt + L: Select Add New Data Source which displays the Shared Data Source Properties window. Let's name our data source DS_SSRS2012Blueprint. For this demonstration, let's use the wizard to create the connection string. As a good practice, I use the wizard for setting up connection strings for my data connections. Aside from convenience, I'm quite confident that I'm getting the right connections that I want. Another option for setting the connection is through the Connection Properties dialog box, as shown in the next screenshot. Clicking on the Edit button next to the connection string box displays the Connection Properties dialog box: Shared versus embedded data sources and datasets: as a good practice, always use shared data sources and shared datasets where appropriate. One characteristic of a productive development project is using reusable objects as much as possible. For the connection, one option is to manually specify the connection string as shown: Data Source=localhost;Initial Catalog=AdventureWorks2012 We may find this option as a convenient way of creating our data connections. But if you're new to the report environment you're currently working on, you may find setting up the connection string manually more cumbersome than setting it up through the wizard. Always test the connection before saving your data source. After testing, click on the OK buttons on both dialog boxes. Defining the dataset for the project Our next step is to create the shared dataset for the project. Before doing that, let's create a stored procedure named dbo.uspSalesDetails. This is going to be the query for our dataset. Download the T-SQL codes included in this article if you haven't done so already. We're going to use the T-SQL file named uspSalesDetails_Ch01.sql for this article. We will use the same stored procedure for this whole article, unless otherwise indicated. Right-click on the Shared Datasets folder in Solution Explorer, just like we did when we created the data source. That displays the Shared Datasets Properties dialog. Let's name our dataset ds_SalesDetailReport. We use the query type stored procedure, and select or type uspSalesDetails on the Select or enter stored procedure name drop-down combo box. Click on OK when you're done: Before we work on the report itself, let's examine our dataset. In the Solution Explorer window, double-click on the dataset ds_SalesDetailReport.rsd, which displays the Shared Dataset Properties dialog box. Notice that the fields returned by our stored procedure have been automatically detected by the report designer. You can rename the field as shown: Ad-hoc Query (Text Query Type) versus Stored Procedure: as a good practice, always use a stored procedure where a query is used. The primary reason for this is that a stored procedure is compiled into a single execution plan. Using stored procedures will also allow you to modify certain elements of your reports without modifying the actual report. Creating the report file Now, we're almost ready to build our first report. We will create our report by building it from scratch by performing the following steps: Going back to the Solution Explorer window, right-click on the Reports folder. Please take note that selecting the Add New Report option will initialize Report Wizard. Use the wizard to build simple tabular or matrix reports. Go ahead if you want to try the wizard but for the purpose of our demonstration, we'll skip the wizard. Select Add, instead of Add New Report, then select New Item: Selecting New Item displays the Add New Item dialog box as shown in the following screenshot. Choose the Report template (default report template) in the template window. Name the report SalesDetailsReport.rdl. Click on the Add button to add the report to our project: Clicking on the Add button displays the empty report in the report designer. It looks similar to the following screenshot: Creating a parameterized report You may have noticed that the stored procedure we created for the shared dataset is parameterized. It has the following parameters: It's a good practice to test all the queries on the database just to make sure we get the datasets that we need. Doing so will eliminate a lot of data quality issues during report execution. This is also the best time to validate all our data. We want our report consumers to have the correct data that is needed for making critical decisions. Let's execute the stored procedure in SQL Server Management Studio (SSMS) and take a look at the execution output. We want to make sure that we're getting the results that we want to have on the report. Now, we add a dataset to our report based on the shared dataset that we had previously created: Right-click on the Datasets folder in the Report Data window. If it's not open, you can open it by navigating to Menu | View | Report Data, or press Ctrl + Alt + D: Selecting Add Dataset displays the Dataset Properties. Let's name our report dataset tblSalesReport. We will use this dataset as the underlying data for the table element that we will create to hold our report data. Indicate that we want to use a shared dataset. A list of the project shared datasets is displayed. We only have one at this point, which is the ds_SalesDetailsReport. Let's select that one, then click on OK. Going back to the Report Data window, you may notice that we now have more objects under the Parameters and Datasets folders. Switch to the Toolbox window. If you don't see it, then go to Menu | View | Toolbox, or press Ctrl + Alt + X. Double-click or drag a table to the empty surface of the designer. Let's add more columns to the table to accommodate all eight dataset fields. Click on the table, then right-click on the bar on the last column and select Insert Column | Right. To add data to the report, let's drag each element from the dataset to their own cell at the table data region. There are three data regions in SSRS: table, matrix, and list. In SSRS 2012, a fourth data region has been added but you can't see that listed anywhere. It's called tablix. Tablix is not shown as an option because it is built into those three data regions. What we're doing in the preceding screenshot is essentially dragging data into the underlying tablix data region. But how can I add my parameters into the report? you may ask. Well, let's switch to the Preview tab. We should now see our parameters already built into the report because we specified them in our stored procedure. Our report should look similar to the following screenshot:
Read more
  • 0
  • 0
  • 7008

article-image-implementing-opencart-modules
Packt
24 Oct 2013
6 min read
Save for later

Implementing OpenCart Modules

Packt
24 Oct 2013
6 min read
(For more resources related to this topic, see here.) OpenCart is an e-commerce cart application built with its own in-house framework which uses Model-View-Controller (MVC) language pattern thus each module in OpenCart also follows the MVCL patterns. Controller creates logics and gathers data from Model and pass it to display them in the view OpenCart modules have admin/ and catalog/ folders and files in admin/ folder helps in controlling setting of module and files in catalog/ folder handles the presentation layer (front-end). Learning how to clone and write codes for Opencart Modules We assume that you already know PHP and have already installed the OpenCart and familiar with the OpenCart backend and frontend as well as some coding knowledge with PHP. You are going to create Hello World module which just has one input box at the admin, settings for the module and same content are shown in front end. First step on module creation is using a unique name, so there will not be conflict with other modules. The same unique name is used to create the file name and class name to extend controller and model. There are generally 6-8 files that need to be created for each module, and they follow a similar structure. If there is interaction with the database tables, we have to create two extra models. The following screenshot shows the hierarchy of files and folder of OpenCart module. So now you know the basic directory structure of OpenCart module. The file structure is divided into two sections admin and catalog. Admin folders and files deal with the setting of the modules and data handling while the catalog folders and files handles the frontend. Let's start with an easy way to make the module. You are going to make the duplicate of the default google_talk module of OpenCart and change it to the Hello World module. We are using the Dreamweaver to work with files. Changes made at the admin folder Go to admin/controller/module/ and copy google_talk.php and paste in the same folder and rename it to helloworld.php and open it to your favorite text editor, then find the following lines: classControllerModuleGoogleTalk extends Controller { Change the class name to classControllerModuleHelloworld extends Controller { Now look for google_talk and replace all with helloworld as shown in the following screenshot: Then, save the file Go to admin/language/english/module/ and copy google_talk.php and paste in the same folder and rename it to helloworld.php and open it. Then look for the following line of code: $_['entry_code'] = 'Google Talk Code:<br /> <span class="help">Goto <a href="http://www.google.com/talk/service/badge/New" target="_blank"> <u>Create a Google Talk chatback badge</u> </a> and copy &amp; paste the generated code into the text box. </span>'; Replace with the following line of code: $_['entry_code'] = 'Hello World Content'; Then again find Google Talk and replace all with Hello World, and save the file. Go to admin/view/template/module/ and copy the google_talk.tpl file and paste in the same folder and rename it to helloworld.tpl and open it and then find google_talk and replace it with helloworld then save it. Changes made at the catalog folder Go to catalog/controller/module/ and copy the google_talk.php file and paste in the same folder and rename it to helloworld.php and open it and look for the following line: class ControllerModuleGoogleTalk extends Controller { change the class name to class ControllerModuleHelloworld extends Controller { Now look for google_talk and replace all with helloworld and save it. Go to catalog/language/english/module/ and copy the google_talk.php file and paste in the same folder and rename it to helloworld.php and open it and then look for Live Chat and replace it with Hello World then save it. Go to catalog/view/theme/default/template/module/ and copy the google_talk.tpl file and paste in the same folder and rename it to helloworld.tpl. With the preceding files and codes change, our Hello World module is ready to be installed. Now log in to the admin section and go to Extensions | Module, look for the Hello World and click on [install] then click on [Edit]. Then type the content that you would like to show at the frontend in Hello World Content field after that click on the Add Module button and provide the setting as per your need and click on Save. Understanding the global Library methods used in OpenCart OpenCart has many predefined methods which can be called anywhere like in the controller or in the model and as well as in the view template files as per the need. You can find system level library files at system/library/. We have defined all the library functions so that it is easy for programmers to use it. For example: $this->customer->login($email, $password, $override = false) Log a customer in. It checks for the customer username and password if $override is passed false, else only for current logged in status and the e-mail. If it finds the correct entry then the cart entry, wishlist entries are retrieved. As well as customer ID, first name, last name, e-mail, telephone, fax, newsletter subscription status, customer group ID, and address ID are globally accessible for the customer. It also updates the customer IP address from where it logs in. Developing and customizing modules, pages, order totals, shipping, and payments extensions in OpenCart We describe the featured module of OpenCart, create feedback module and tips module, and describe and show how codes work and are managed. We helped to learn how to make pages and modules in OpenCart as well as let visualize the uses of database structure; how data are saved as per language, as per store so it helps OpenCart programmers to understand and follow the patterns of Opencart coding style. We describe codes how form works, how to list out the data from database, how edit works in module, and how they are saved. Show them how to code shipping module in OpenCart as well as total order modules and payment modules. We have outlined how templates, models, and controllers work for extensions. Summary In this way we have learned how to clone and write codes for OpenCart modules and the changes made at the admin and catalog folder. We also learned the global library methods used in OpenCart. Also, covered all ways to code the OpenCart extensions. Resources for Article: Further resources on this subject: Upgrading OpenCart [Article] OpenCart FAQs [Article] OpenCart: Layout Structure [Article]
Read more
  • 0
  • 0
  • 3349

Packt
24 Oct 2013
13 min read
Save for later

Using Media Files – playing audio files

Packt
24 Oct 2013
13 min read
(For more resources related to this topic, see here.) Playing audio files JUCE provides a sophisticated set of classes for dealing with audio. This includes: sound file reading and writing utilities, interfacing with the native audio hardware, audio data conversion functions, and a cross-platform framework for creating audio plugins for a range of well-known host applications. Covering all of these aspects is beyond the scope of this article, but the examples in this section will outline the principles of playing sound files and communicating with the audio hardware. In addition to showing the audio features of JUCE, in this section we will also create the GUI and autogenerate some other aspects of the code using the Introjucer application. Creating a GUI to control audio file playback Create a new GUI application Introjucer project of your choice, selecting the option to create a basic window. In the Introjucer application, select the Config panel, and select Modules in the hierarchy. For this project we need the juce_audio_utils module (which contains a special Component class for configuring the audio device hardware); therefore, turn ON this module. Even though we created a basic window and a basic component, we are going to create the GUI using the Introjucer application. Navigate to the Files panel and right-click (on the Mac, press control and click) on the Source folder in the hierarchy, and select Add New GUI Component… from the contextual menu. When asked, name the header MediaPlayer.h and click on Save. In the Files hierarchy, select the MediaPlayer.cpp file. First select the Class panel and change the Class name from NewComponent to MediaPlayer. We will need four buttons for this basic project: a button to open an audio file, a Play button, a Stop button, and an audio device settings button. Select the Subcomponents panel, and add four TextButton components to the editor by right-clicking to access the contextual menu. Space the buttons equally near the top of the editor, and configure each button as outlined in the table as follows: Purpose member name name text background (normal) Open file openButton open Open... Default Play/pause file playButton play Play Green Stop playback stopButton stop Stop Red Configure audio settingsButton settings Audio Settings... Default Arrange the buttons as shown in the following screenshot: For each button, access the mode pop-up menu for the width setting, and choose Subtracted from width of parent. This will keep the right-hand side of the buttons the same distance from the right-hand side of the window if the window is resized. There are more customizations to be done in the Introjucer project, but for now, make sure that you have saved the MediaPlayer.h file, the MediaPlayer.cpp file, and the Introjucer project before you open your native IDE project. Make sure that you have saved all of these files in the Introjucer application; otherwise the files may not get correctly updated in the file system when the project is opened in the IDE. In the IDE we need to replace the MainContentComponent class code to place a MediaPlayer object within it. Change the MainComponent.h file as follows: #ifndef __MAINCOMPONENT_H__#define __MAINCOMPONENT_H__#include "../JuceLibraryCode/JuceHeader.h"#include "MediaPlayer.h"class MainContentComponent : public Component{public:MainContentComponent();void resized();private:MediaPlayer player;};#endif Then, change the MainComponent.cpp file to: #include "MainComponent.h"MainContentComponent::MainContentComponent(){addAndMakeVisible (&player);setSize (player.getWidth(),player.getHeight());}void MainContentComponent::resized(){player.setBounds (0, 0, getWidth(), getHeight());} Finally, make the window resizable in the Main.cpp file, and build and run the project to check that the window appears as expected. Adding audio file playback support Quit the application and return to the Introjucer project. Select the MediaPlayer.cpp file in the Files panel hierarchy and select its Class panel. The Parent classes setting already contains public Component. We are going to be listening for state changes from two of our member objects that are ChangeBroadcaster objects. To do this, we need our MediaPlayer class to inherit from the ChangeListener class. Change the Parent classes setting such that it reads: public Component, public ChangeListener Save the MediaPlayer.h file, the MediaPlayer.cpp file, and the Introjucer project again, and open it into your IDE. Notice in the MediaPlayer.h file that the parent classes have been updated to reflect this change. For convenience, we are going to add some enumerated constants to reflect the current playback state of our MediaPlayer object, and a function to centralize the change of this state (which will, in turn, update the state of various objects, such as the text displayed on the buttons). The ChangeListener class also has one pure virtual function, which we need to add. Add the following code to the [UserMethods] section of MediaPlayer.h: //[UserMethods]-- You can add your own custom methods...enum TransportState {Stopped,Starting,Playing,Pausing,Paused,Stopping};void changeState (TransportState newState);void changeListenerCallback (ChangeBroadcaster* source);//[/UserMethods] We also need some additional member variables to support our audio playback. Add these to the [UserVariables] section: //[UserVariables] -- You can add your own custom variables...AudioDeviceManager deviceManager;AudioFormatManager formatManager;ScopedPointer<AudioFormatReaderSource> readerSource;AudioTransportSource transportSource;AudioSourcePlayer sourcePlayer;TransportState state;//[/UserVariables] The AudioDeviceManager object will manage our interface between the application and the audio hardware. The AudioFormatManager object will assist in creating an object that will read and decode the audio data from an audio file. This object will be stored in the ScopedPointer<AudioFormatReaderSource> object. The AudioTransportSource object will control the playback of the audio file and perform any sampling rate conversion that may be required (if the sampling rate of the audio file differs from the audio hardware sampling rate). The AudioSourcePlayer object will stream audio from the AudioTransportSource object to the AudioDeviceManager object. The state variable will store one of our enumerated constants to reflect the current playback state of our MediaPlayer object. Now add some code to the MediaPlayer.cpp file. In the [Constructor] section of the constructor, add following two lines: playButton->setEnabled (false);stopButton->setEnabled (false); This sets the Play and Stop buttons to be disabled (and grayed out) initially. Later, we enable the Play button once a valid file is loaded, and change the state of each button and the text displayed on the buttons, depending on whether the file is currently playing or not. In this [Constructor] section you should also initialize the AudioFormatManager as follows: formatManager.registerBasicFormats(); This allows the AudioFormatManager object to detect different audio file formats and create appropriate file reader objects. We also need to connect the AudioSourcePlayer, AudioTransportSource and AudioDeviceManager objects together, and initialize the AudioDeviceManager object. To do this, add the following lines to the [Constructor] section: sourcePlayer.setSource (&transportSource);deviceManager.addAudioCallback (&sourcePlayer);deviceManager.initialise (0, 2, nullptr, true); The first line connects the AudioTransportSource object to the AudioSourcePlayer object. The second line connects the AudioSourcePlayer object to the AudioDeviceManager object. The final line initializes the AudioDeviceManager object with: The number of required audio input channels (0 in this case). The number of required audio output channels (2 in this case, for stereo output). An optional "saved state" for the AudioDeviceManager object (nullptr initializes from scratch). Whether to open the default device if the saved state fails to open. As we are not using a saved state, this argument is irrelevant, but it is useful to set this to true in any case. The final three lines to add to the [Constructor] section to configure our MediaPlayer object as a listener to the AudioDeviceManager and AudioTransportSource objects, and sets the current state to Stopped: deviceManager.addChangeListener (this);transportSource.addChangeListener (this);state = Stopped; In the buttonClicked() function we need to add some code to the various sections. In the [UserButtonCode_openButton] section, add: //[UserButtonCode_openButton] -- add your button handler...FileChooser chooser ("Select a Wave file to play...",File::nonexistent,"*.wav");if (chooser.browseForFileToOpen()) {File file (chooser.getResult());readerSource = new AudioFormatReaderSource(formatManager.createReaderFor (file), true);transportSource.setSource (readerSource);playButton->setEnabled (true);}//[/UserButtonCode_openButton] When the openButton button is clicked, this will create a FileChooser object that allows the user to select a file using the native interface for the platform. The types of files that are allowed to be selected are limited using the wildcard *.wav to allow only files with the .wav file extension to be selected. If the user actually selects a file (rather than cancels the operation), the code can call the FileChooser::getResult() function to retrieve a reference to the file that was selected. This file is then passed to the AudioFormatManager object to create a file reader object, which in turn is passed to create an AudioFormatReaderSource object that will manage and own this file reader object. Finally, the AudioFormatReaderSource object is connected to the AudioTransportSource object and the Play button is enabled. The handlers for the playButton and stopButton objects will make a call to our changeState() function depending on the current transport state. We will define the changeState() function in a moment where its purpose should become clear. In the [UserButtonCode_playButton] section, add the following code: //[UserButtonCode_playButton] -- add your button handler...if ((Stopped == state) || (Paused == state))changeState (Starting);else if (Playing == state)changeState (Pausing);//[/UserButtonCode_playButton] This changes the state to Starting if the current state is either Stopped or Paused, and changes the state to Pausing if the current state is Playing. This is in order to have a button with combined play and pause functionality. In the [UserButtonCode_stopButton] section, add the following code: //[UserButtonCode_stopButton] -- add your button handler...if (Paused == state)changeState (Stopped);elsechangeState (Stopping);//[/UserButtonCode_stopButton] This sets the state to Stopped if the current state is Paused, and sets it to Stopping in other cases. Again, we will add the changeState() function in a moment, where these state changes update various objects. In the [UserButtonCode_settingsButton] section add the following code: //[UserButtonCode_settingsButton] -- add your button handler...bool showMidiInputOptions = false;bool showMidiOutputSelector = false;bool showChannelsAsStereoPairs = true;bool hideAdvancedOptions = false;AudioDeviceSelectorComponent settings (deviceManager,0, 0, 1, 2,showMidiInputOptions,showMidiOutputSelector,showChannelsAsStereoPairs,hideAdvancedOptions);settings.setSize (500, 400);DialogWindow::showModalDialog(String ("Audio Settings"),&settings,TopLevelWindow::getTopLevelWindow (0),Colours::white,true); //[/UserButtonCode_settingsButton] This presents a useful interface to configure the audio device settings. We need to add the changeListenerCallback() function to respond to changes in the AudioDeviceManager and AudioTransportSource objects. Add the following to the [MiscUserCode] section of the MediaPlayer.cpp file: //[MiscUserCode] You can add your own definitions...void MediaPlayer::changeListenerCallback (ChangeBroadcaster* src){if (&deviceManager == src) {AudioDeviceManager::AudioDeviceSetup setup;deviceManager.getAudioDeviceSetup (setup);if (setup.outputChannels.isZero())sourcePlayer.setSource (nullptr);elsesourcePlayer.setSource (&transportSource);} else if (&transportSource == src) {if (transportSource.isPlaying()) {changeState (Playing);} else {if ((Stopping == state) || (Playing == state))changeState (Stopped);else if (Pausing == state)changeState (Paused);}}}//[/MiscUserCode] If our MediaPlayer object receives a message that the AudioDeviceManager object changed in some way, we need to check that this change wasn't to disable all of the audio output channels, by obtaining the setup information from the device manager. If the number of output channels is zero, we disconnect our AudioSourcePlayer object from the AudioTransportSource object (otherwise our application may crash) by setting the source to nullptr. If the number of output channels becomes nonzero again, we reconnect these objects. If our AudioTransportSource object has changed, this is likely to be a change in its playback state. It is important to note the difference between requesting the transport to start or stop, and this change actually taking place. This is why we created the enumerated constants for all the other states (including transitional states). Again we issue calls to the changeState() function depending on the current value of our state variable and the state of the AudioTransportSource object. Finally, add the important changeState() function to the [MiscUserCode] section of the MediaPlayer.cpp file that handles all of these state changes: void MediaPlayer::changeState (TransportState newState){if (state != newState) {state = newState;switch (state) {case Stopped:playButton->setButtonText ("Play");stopButton->setButtonText ("Stop");stopButton->setEnabled (false);transportSource.setPosition (0.0);break;case Starting:transportSource.start();break;case Playing:playButton->setButtonText ("Pause");stopButton->setButtonText ("Stop");stopButton->setEnabled (true);break;case Pausing:transportSource.stop();break;case Paused:playButton->setButtonText ("Resume");stopButton->setButtonText ("Return to Zero");break;case Stopping:transportSource.stop();break;}}} After checking that the newState value is different from the current value of the state variable, we update the state variable with the new value. Then, we perform the appropriate actions for this particular point in the cycle of state changes. These are summarized as follows: In the Stopped state, the buttons are configured with the Play and Stop labels, the Stop button is disabled, and the transport is positioned to the start of the audio file. In the Starting state, the AudioTransportSource object is told to start. Once the AudioTransportSource object has actually started playing, the system will be in the Playing state. Here we update the playButton button to display the text Pause, ensure the stopButton button displays the text Stop, and we enable the Stop button. If the Pause button is clicked, the state becomes Pausing, and the transport is told to stop. Once the transport has actually stopped, the state changes to Paused, the playButton button is updated to display the text Resume and the stopButton button is updated to display Return to Zero. If the Stop button is clicked, the state is changed to Stopping, and the transport is told to stop. Once the transport has actually stopped, the state changes to Stopped (as described in the first point). If the Return to Zero button is clicked, the state is changed directly to Stopped (again, as previously described). When the audio file reaches the end of the file, the state is also changed to Stopped. Build and run the application. You should be able to select a .wav audio file after clicking the Open... button, play, pause, resume, and stop the audio file using the respective buttons, and configure the audio device using the Audio Settings… button. The audio settings window allows you to select the input and output device, the sample rate, and the hardware buffer size. It also provides a Test button that plays a tone through the selected output device. Summary This article has covered a few of the techniques for dealing with audio files in JUCE. The article has given only an introduction to get you started; there are many other options and alternative approaches, which may suit different circumstances. The JUCE documentation will take you through each of these and point you to related classes and functions. Resources for Article: Further resources on this subject: Quick start – media files and XBMC [Article] Audio Playback [Article] Automating the Audio Parameters – How it Works [Article]
Read more
  • 0
  • 0
  • 2441

article-image-illuminating-scene
Packt
24 Oct 2013
3 min read
Save for later

Illuminating a Scene

Packt
24 Oct 2013
3 min read
(For more resources related to this topic, see here.) Working with lights Before starting to explain about lights, we need to learn how to create and manipulate them. Once you know how to handle them, you will be ready to start learning the who-is-who in the lightning stage. Let's start with the basics. Adding a light Lights are handled in modo just like regular items. You can move, rotate, and scale them, and of course, tweak their properties. By default, a newly created scene has got a default light already. You can use it, change its type, or add as many as you need. In order to add a new light you should go to the Item List tab, and then click on the Add Item button. In the drop-down menu go to Lights, then choose the type of light you want. The other way to do this is by using the top menu. Navigate to Item | Create Light and choose the type you want. Setting the type of a light You can always change the type of the light just created (or change an existent light). In the Item List tab, right-click the light you want to change, and from the menu click on Change Type, then choose the type you want for your light. Placing lights As said previously, lights are like all other regular items. So you can move, rotate, and scale them as you need. You will have the following two ways of placing a light: Direct manipulation: Working in item mode, click on the light on any of the viewports—or directly in the Item List tab— and use the corresponding tools (W for moving, R for scaling, or Y for rotating). Subjective manipulation: A more interesting and practical way to move a light is by changing the viewport to light view mode. Once you change it, your view will be literally inside the light, so the direction you are facing will be the direction of the light. In this view, use your standard viewport controls to orientate the light. Enabling/disabling lights Usually, there are occasions when you need to turn off a light, or a number of them. The first thought would be turning its intensity value to zero, but there is a more practical way to temporarily disable a light. If you take a look at the items list, you will see a column on the left of the panel showing a little eye icon. That column shows the visibility state of each item. The eye means that it's visible, and you can click on that icon to totally disable the light (or any item, in fact), and click on it again to enable it back. Of course you can do rest of the basic operations with the lights, as with other kinds of items including enabling/disabling them, grouping them in a single folder, and so on.
Read more
  • 0
  • 0
  • 2154
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 €18.99/month. Cancel anytime
article-image-routing-and-grouping-techniques
Packt
24 Oct 2013
13 min read
Save for later

Routing and grouping techniques

Packt
24 Oct 2013
13 min read
(For more resources related to this topic, see here.) Easy audio grouping Pro Tools offers an interesting shortcut to assist the process. To create a new audio group, the simplest way is to follow these steps: Select the tracks to be grouped. Press option + shift (Mac) or Alt + Shift (Windows) and click on the track output. Select New Track and create a mono or stereo auxiliary track. The bus name and routing will be automatically assigned. We can later select or show the corresponding tracks associated with any type of input or output by right-clicking on any track input or output. This also works for hardware sends. Multiple track outputs In Pro Tools, a track can have as many outputs as you like (as long as you have available voices); it can even be routed to all available outputs simultaneously. Hold the control key (Mac) or Start key (Windows) and click on the track's output to add another output. When a track is routed to multiple outputs, a + button is displayed like this: Routing to multiple outputs; this track is assigned to Mixbus and other outputs There are also key modifiers that we can use. Key modifier Mac Windows Add the desired output to all the tracks control + option Start + Alt Add the desired output to the selected tracks control + option + shift Start + Alt + Shift Stemming with multiple outputs Unfortunately, there is no easy way of creating stems or multitrack bounces automatically with Pro Tools 10; the process remains mainly manual. Pro Tools 11 addresses some of these issues in the next section, but for now, assuming that our master fader track contains processing, our first and only stemming option is to solo the appropriate tracks and use the bounce to disk function. If we have no processing for our master output fader, we can bounce inside the session instead by assigning multiple outputs to tracks or buses by grouping them and creating auxiliary sends. Using the key modifiers defined previously, you can quickly select tracks and assign their outputs or auxiliary sends to new audio tracks for recording. To stem tracks to a new audio track without affecting their current routing, use the following methods. Using multiple outputs Select the tracks. Hold control + option + shift (Mac) or Start + Alt + Shift (Windows). Click on New track from the track output menu. Create the appropriate audio track and record. Using auxiliary sends Select the tracks. Hold option + shift (Mac) or Alt + Shift (Windows). Click on N ew track from the track output menu. Create the appropriate audio track and record. We can select the desired recording format from the session window accessible from Setup | Session . If you're recording the track at anything other than a 32-bit float, make sure your levels do not exceed 0 dBfs. We can also use complex mixing routing techniques to our advantage, as this will give us many summing points from which we can easily create the New track stems. We will discuss more on how to increase routing complexity to create more summing points inside the mix. Sound layering Using auxiliary tracks is the best way to perform parallel processing in Pro Tools, but multiple output routing can also be very useful for sound layering, keeping your track sends free for other effects. By sending the output to multiple auxiliary tracks, we can very easily add textures and effects. As an example, I like to layer my basses this way with different distortions and other parallel processing. To me, sound layering is more suited to multiple outputs because their relative level mostly stays the same. Stemming with Pro Tools 11 Pro Tools 11 brings new offline bouncing capabilities with added simultaneous bounce from internal busses or physical outputs. Inside the Bounce to disk window, click on the + button to add another source to a maximum of 16. Each source can have a different file format, from mono to multichannel audio. Because we can bounce physical outputs, Pro Tools 11 also allows for stemming tracks that are processed using master fader inserts. These new features added to offline bounces have drastically improved the Pro Tools 10 workflow, saving us a lot of time and leaving us with the following two main stemming options: While working with multiple outputs, we can source our stem from the physical outputs directly While summing inside Pro Tools, it becomes a lot more relevant to group as many tracks as we can to create available bounce sources Increasing mixing complexity One of the biggest advantages of mixing inside a DAW over traditional analogue console setups is its expanded routing capabilities, giving us far more control over the signal. In this section, I'd like to discuss how to use buses to create more complex mixes, that is, creating extra summing points for several uses and comparing the digital approach over a traditional frontend analog mixing console setup. As we saw previously, Pro Tools 10 introduced a new 64-bit floating point mixer, allowing for almost unlimited headroom and greater precision, which made digital summing even more digitally perfect. This means that it is entirely up to the engineer to create his sound textures through recording or digital processing. Pro Tools 11 took this quest for digital perfection even further with a full 64-bit path. On the other hand, analog is technically flawed and has always been; every single piece of circuitry will color the signal in various amounts, but these are those imperfections that many of us came to love and successfully or not tried to recreate in the digital domain. A digital mixer will sum signals with a far lower harmonic distortion. Applying different distortions is therefore the key to restore an analog feel to the mix. The first step toward this approach is to increase the mixer's complexity to be able to apply different types of distortions in many more places. Audio groups or buses are the most basic routing idea. As an example, working with drums, I would group all the kicks together, the snare together, the toms together, the overheads together, the rooms together, and so on. Those subbuses will then be bused to a master drum bus. This allows us to do the following: Process multiple microphones at a time Bounce stems more easily later Have greater control over my individual drum sounds To me, routing is the heart of digital mixing and making it as complex as possible begins to open many new creative doors. But we can go a step further. My drum bus will be first bused to my rhythm bus, then to my instrumental bus, and finally to my mix bus. This introduces more advanced groupings based on other criteria such as rhythm or instrumental. This might not seem very useful at first, but it will make you think about the track in different ways, giving you control at every stages of the mix. Here is an example of what a complex mix would look like: An example of a more complex routing diagram I might not use all the possibilities all the time, and this is only a small example. But this helped me very much over the years to create better depth in my mixes and also considerably speed up my workflow while creating stem mixes. I have instant access to many more summing points in my mixes, allowing me to group and differentiate even more sounds from each other. The previous diagram only shows how to increase a mix complexity by busing tracks into each other, but these summing points are also open doors to some very effective parallel processing. Default output bus options While working with multiple buses, it becomes quite hard to systematically remember to update the track output to the user's Mixbus. We can change the default track's Pro Tools's default bus output through Preferences | I/O | Output | Default Output Bus . Along with changing the default bus output, there are a few key modifiers worth remembering to assign tracks to the desired output or the bus. Key modifier Mac Windows Assign all the tracks to the same I/O option Alt Assign all the selected tracks to the same I/O option + shift Alt + Shift Assign all the tracks' I/O incrementally command + option Ctrl + Alt Assign all the selected tracks' I/O incrementally command + option + shift Ctrl + Alt + Shift Greater control over parallel processing Parallel processing is widely used for mixing. It allows adding to the signal while preserving the original content. It usually sounds a lot better to mix this way rather than process everything on groups; drums can particularly benefit from this technique. The main issue with group processing is that it tends to make everything sound very clinical and lifeless, especially if too much dynamic treatment is applied. Digital dynamic processors especially do not compare well to their analog counterpart when it comes to attenuating levels without taking life out of the recording. For these reasons, I tend to complement my mixes with a lot of parallel processing to increase harmonics, depth, loudness, and focus frequencies rather than cutting or boosting them too much. Parallel processing allows me to get a richer sound. Creating parallel processing requires extra buses. We can use the track sends, multiple outputs, or duplicate the track to achieve quick results. As an example, using track sends in pre fader mode, I can quickly create a perfect copy of my signal independent of my main mix level to process and automate creatively. Select the tracks and press command + G (Mac) or Ctrl + G (Windows) to create a new group. Inside the Create group window, disable Follow Global and select Mix or Edit/Mix and the appropriate send and settings you would like to link.In my example, I will only link Volume and Mute . Now that we have created the group, a neat thing to do would be to copy the existing track volume levels to the send. To do so, perform the following steps: Press command + option + H (Mac) or Ctrl + Alt + H (Windows). The Copy to Send window appears. Select the correct destination send and the parameter to copy. We can copy everything, even automation, to have the exact same mix across the entire song. Now with the tracks still selected, display any send window, hold option + shift (Mac) or Alt + Shift (Windows), and click on PRE to make the sends pre fader and have the auxiliary mix independent of the main mix. Having copied the current mix to the send, we can not only use it as a perfect parallel copy, but now we also have the choice to alter the balance between the current mix and the send to better suit the type of parallel processing we will be applying. Trying to improve the low end might not require too much high frequency information, so I might change the balance to pull down the appropriate tracks. On the other hand, trying to improve my high end might benefit from pulling down low frequency content. Copying mix to send is also very useful while setting up cue mixes for recording. Using the copy to send function is very rewarding while working with parallel processing, but the default mixer's send view does not look very user friendly. Pro Tools offers an alternate way of displaying the send information inside the mixer window. We can focus on a particular send to display mini fader sends and level information. To do so, let's navigate to View | Sends A-E or View | Sends F-J and select the particular send you would like to display. We can also press command + click (Mac) or Ctrl + click (Windows) from the left-hand side of the send in the mixer view. We can display a maximum of two sends at a time in Pro Tools 10 and all of them simultaneously in Pro Tools 11, giving a great matrix view for parallel processing or headphone mixes. This new functionality is accessible from View | Expanded Sends . Pro Tools 11 Expanded Sends view, showing Sends A-E We now have a nice send display with linked parameters: To change the level of all the grouped tracks, keeping their relative level with the group active, just move one of the send fader To change one send value without affecting the entire group, hold control (Mac) or Start (Windows) and move the appropriate fader Advanced side chain Side chaining is one of the most commonly used techniques for music production, sound design, and mixing. Pro Tools allow for some interesting side chaining possibilities, allowing us to not only mix many different tracks and process them, but also to play with their timing by manipulating the automatic delay compensation. For bass I will stay with my drum recording and take the classic example of compressing the bass track according to the kick. By doing so, we make the groove tighter, reinforcing the impression that the bass player is locked to the drum groove. To do so, I could use the Bomb Factory BF76 plugin on the bass with my side chain activated on bus 15 carrying the kick. Once it is set up, every time the kick hits, the bass track gain will be pulled down, enhancing the groove and also giving more space in the mix for the "kick drum," but that is not all. Since Pro Tools uses buses to create external side chains, we can send as many signals as we'd like to control the bass accordingly. As an example, I could have the kick not only during the verses but could also add some of my percussion to the side chain mix. Tweaking the side chain balance mix can give you very natural results and give the impression that the bass player is grooving more with the entire performance. When we group multiple signals together into a side chain, we can also alter their frequency spectrum or even their dynamics to create different compression behaviors. Because my side chain information is contained on a bus, I can create a master fader or auxiliary track to process the audio before it reaches my plugin. While working with recorded drums, it might be useful to gate the side chain bus a lot more aggressively, since it cannot be heard. We can also boost one of the low kick frequencies and cut the high end to avoid hats, crashes, and so on triggering unwanted compressions. To do so, we could boost the low frequencies first and then gate the result more aggressively. Summary In this article, we learned how to use internal routing and automations to increase creative output. Resources for Article: Further resources on this subject: Audio Playback [Article] Automating the Audio Parameters – How it Works [Article] Getting Started with Adobe Premiere Pro CS6 Hotshot [Article]
Read more
  • 0
  • 0
  • 5211

article-image-major-sdk-components
Packt
24 Oct 2013
11 min read
Save for later

Major SDK components

Packt
24 Oct 2013
11 min read
(For more resources related to this topic, see here.) Controller The Leap::Controller class is a liaison between the controller and your code. Whenever you wish to do anything at all with the device you must first go through your controller. From a controller instance we can interact with the device configuration, detected displays, current and past frames, and set up event handling with our listener subclass. Config An instance of the Config class can be obtained from a controller. It provides a key/value interface to modify the operation of the Leap device and driver behavior. Some of the options available are: Robust mode : Somewhat slower frame processing but works better with less light. Low resource mode : Less accurate and responsive tracking, but uses less CPU and USB bandwidth. Tracking priority : Can prioritize either precision of tracking data or the rate at which data is sampled (resulting in approximately 4x data frame-rate boost), or a balance between the two (approximately 2x faster than the precise mode). Flip tracking : Allows you to use the controller with the USB cable coming out of either side. This setting simply flips the positive and negative coordinates on the X-axis. Screen A controller may have one or more calibratedScreens, which are computer displays in the field of view of the controller, which have a known position and dimensions. Given a pointable direction and a screen we can determine what the user is pointing at. Math Several math-related functions and types such as Leap::Vector, Leap::Matrix, and Leap::FloatArray are provided by LeapMath.h. All points in space, screen coordinates, directions, and normal are returned by the API as three-element vectors representing X, Y, and Z coordinates or unit vectors. Frame The real juicy information is stored inside each Frame. A Frame instance represents a point in time in which the driver was able to generate an updated view of its world and detect where screens, your hands, and pointables are. Hand At present the only body parts you can use with the controller are your hands. Given a frame instance we can inspect the number of hands in the frame, their position and rotation, normal vectors, and gestures. The hand motion API allows you to compare two frames and determine if the user has performed a translation, rotation, or scaling gesture with their hands in that time interval. The methods we can call to check for these interactions are: Leap::Hand::translation(sinceFrame): Translation (also known as movement) returned as a Leap::Vector including the direction of the movement of the hand and the distance travelled in millimeters. Leap::Hand::rotationMatrix(sinceFrame), ::rotationAxis(sinceFrame), ::rotationAngle(sinceFrame, axisVector): Hand rotation, either described as a rotation matrix, vector around an axis or float angle around a vector between –π and π radians (that's -180° to 180° for those of you who are a little rusty with your trigonometry). Leap::Hand::scaleFactor(sinceFrame): Scaling represents the distance between two hands. If the hands are closer together in the current frame compared to sinceFrame, the return value will be less than 1.0 but greater than 0.0. If the hands are further apart the return value will be greater than 1.0 to indicate the factor by which the distance has increased. Pointable A Hand also can contain information about Pointable objects that were recognized in the frame as being attached to the hand. A distinction is made between the two different subclasses of pointable objects, Tool, which can be any slender, long object such as a chopstick or a pencil, and Finger, whose meaning should be apparent. You can request either fingers or tools from a Hand, or a list of pointables to get both if you don't care. Finger positioning Suppose we want to know where a user's fingertips are in space. Here's a short snippet of code to output the spatial coordinates of the tips of the fingers on a hand that is being tracked by the controller: if (frame.hands().empty()) return; const Leap::Hand firstHand = frame.hands()[0]; const Leap::FingerList fingers = firstHand.fingers(); Here we obtain a list of the fingers on the first hand of the frame. For an enjoyable diversion let's output the locations of the fingertips on the hand, given in the Leap coordinate system: for (int i = 0; i < fingers.count(); i++) { const Leap::Finger finger = fingers[i]; std::cout << "Detected finger " << i << " at position (" << finger.tipPosition().x << ", " << finger.tipPosition().y << ", " << finger.tipPosition().z << ")" << std::endl; } This demonstrates how to get the position of the fingertips of the first hand that is recognized in the current frame. If you hold three fingers out the following dazzling output is printed: Detected finger 0 at position (-119.867, 213.155, -65.763) Detected finger 1 at position (-90.5347, 208.877, -61.1673) Detected finger 2 at position (-142.919, 211.565, -48.6942) While this is clearly totally awesome, the exact meaning of these numbers may not be immediately apparent. For points in space returned by the SDK the Leap coordinate system is used. Much like our forefathers believed the Earth to be the cornerstone of our solar system, your Leap device has similar notions of centricity. It measures locations by their distance from the Leap origin, a point centered on the top of the device. Negative X values represent a point in space to the left of the device, positive values are to the right. The Z coordinates work in much the same way, with positive values extending towards the user and negative values in the direction of the display. The Y coordinate is the distance from the top of the device, starting 25 millimeters above it and extending to about 600 millimeters (two feet) upwards. Note that the device cannot see below itself, so all Y coordinates will be positive. An example of cursor control By now we are feeling pretty saucy, having diligently run the sample code thus far and controlling our computer in a way never before possible. While there is certain utility and endless amusement afforded by printing out finger coordinates while waving your hands in the air and pretending to be a magician, there are even more exciting applications waiting to be written, so let's continue onwards and upwards. Until computer-gesture interaction is commonplace, pretending to be a magician while you test the functionality of Leap SDK is not recommended in public places such as coffee shops. In some cultures it is considered impolite to point at people. Fortunately your computer doesn't have feelings and won't mind if we use a pointing gesture to move its cursor around (you can even use a customarily offensive finger if you so choose). In order to determine where to move the cursor, we must first locate the position on the display that the user is pointing at. To accomplish this we will make use of the screen calibration and detection API in the SDK. If you happen to leave your controller near a computer monitor it will do its best to try and determine the location and dimensions of the monitor by looking for a large, flat surface in its field of view. In addition you can use the complementary Leap calibration functionality to improve its accuracy if you are willing to take a couple of minutes to point at various dots on your screen. Note that once you have calibrated your screen, you should ensure that the relative positions of the Leap and the screen do not change. Once your controller has oriented itself within your surroundings, hands and display, you can ask your trusty controller instance for a list of detected screens: // get list of detected screens const Leap::ScreenList screens = controller.calibratedScreens(); // make sure we have a detected screen if (screens.empty()) return;const Leap::Screen screen = screens[0]; We now have a screen instance that we can use to find out the physical location in space of the screen as well as its boundaries and resolution. Who cares about all that though, when we can use the SDK to compute where we're pointing to with the intersect() method? // find the first finger or tool const Leap::Frame frame = controller.frame(); const Leap::HandList hands = frame.hands(); if (hands.empty()) return; const Leap::PointableList pointables = hands[0].pointables(); if (pointables.empty()) return; const Leap::Pointable firstPointable = pointables[0]; // get x, y coordinates on the first screen const Leap::Vector intersection = screen.intersect( firstPointable, true, // normalize 1.0f // clampRatio ); The vector intersection contains what we want to know here; the pixel pointed at by our pointable. If the pointable argument to intersect() is not actually pointing at the screen then the return value will be (NaN, NaN, NaN). NaN stands for not a number . We can easily check for the presence of non-finite values in a vector with the isValid() method: if (! intersection.isValid()) return; // print intersection coordinates std::cout << "You are pointing at (" << intersection.x << ", " << intersection.y << ", " << intersection.z << ")" << std::endl; Prepare to be astounded when you point at the middle of your screen and the transfixing message You are pointing at (0.519522, 0.483496, 0) is revealed. Assuming your screen resolution is larger than one pixel on either side, this output may be somewhat unexpected, so let's talk about what screen.intersect(const Pointable &pointable, bool normalize, float clampRatio=1.0f) is returning. The intersect() method draws an imaginary ray from the tip of pointable extending in the same direction as your finger or tool and returns a three-element vector containing the coordinates of the point of intersection between the ray and the screen. If the second parameter normalize is set to false then intersect() will return the location in the leap coordinate system. Since we have no interest in the real world we have set normalize to true, which causes the coordinates of the returned intersection vector to be fractions of the screen width and height. When intersect() returns normalized coordinates, (0, 0, 0) is considered the bottom-left pixel, and (1, 1, 0) is the top-right pixel. It is worth noting that many computer graphics coordinate systems define the top-left pixel as (0, 0) so use caution when using these coordinates with other libraries. There is one last (optional) parameter to the intersect() method, clampRatio, which is used to expand or contract the boundaries of the area at which the user can point, should you want to allow pointing beyond the edges of the screen. Now that we have our normalized screen position, we can easily work out the pixel coordinate in the direction of the user's rude gesticulations: unsigned int x = screen.widthPixels() * intersection.x; // flip y coordinate to standard top-left origin unsigned int y = screen.heightPixels() * (1.0f - intersection.y); std::cout << "You are offending the pixel at (" << x << ", " << y << std::endl; Since intersection.x and intersection.y are fractions of the screen dimensions, simply multiply by the boundary sizes to get our intersection coordinates on the screen. We'll go ahead and leave out the Z-coordinate since it's usually (OK, always) zero. Now for the coup de grace —moving the cursor location, here's how to do it on Mac OS X: CGPoint destPoint = CGPointMake(x, y); CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, de.stPoint); You will need to #include <CoreGraphics/CoreGraphics.h> and link it ( –framework CoreGraphics) to make use of CGDisplayMoveCursorToPoint(). Now all of our hard efforts are rewarded, and we can while away the rest of our days making the cursor zip around with nothing more than a twitch of the finger. At least until our arm gets tired. After a few seconds (or minutes, for the easily-amused) it may become apparent that the utility of such an application is severely limited, as we can't actually click on anything. So maybe you shouldn't throw your mouse away just yet, but read on if you are ready to escape from the shackles of such an antiquated input device. Summary In this article, we learned about the major components of the Leap SDK. We went through the various components of the Leap SDK. Resources for Article: Further resources on this subject: Kinect in Motion – An Overview [Article] Getting started with Kinect for Windows SDK Programming [Article] Getting Started with Kinect [Article]
Read more
  • 0
  • 0
  • 2879

article-image-visualizing-my-social-graph-d3js
Packt
24 Oct 2013
7 min read
Save for later

Visualizing my Social Graph with d3.js

Packt
24 Oct 2013
7 min read
(For more resources related to this topic, see here.) The Social Networks Analysis Social Networks Analysis (SNA) is not new, sociologists have been using it for a long time to study human relationships (sociometry), to find communities and to simulate how information or a disease is spread in a population. With the rise of social networking sites such as Facebook, Twitter, LinkedIn, and so on. The acquisition of large amounts of social network data is easier. We can use SNA to get insight about customer behavior or unknown communities. It is important to say that this is not a trivial task and we will come across sparse data and a lot of noise (meaningless data). We need to understand how to distinguish between false correlation and causation. A good start is by knowing our graph through visualization and statistical analysis. Social networking sites bring us the opportunities to ask questions that otherwise are too hard to approach, because polling enough people is time-consuming and expensive. In this article, we will obtain our social network's graph from Facebook (FB) website in order to visualize the relationships between our friends. Finally we will create an interactive visualization of our graph using D3.js. Getting ready The easiest method to get our friends list is by using a third-party application. Netvizz is a Facebook app developed by Bernhard Rieder, which allows exporting social graph data to gdf and tab formats. Netvizz may export information about our friends such as gender, age, locale, posts, and likes. In order to get our social graph from Netvizz we need to access the link below and giving access to your Facebook profile. https://apps.facebook.com/netvizz/ As is shown in the following screenshot, we will create a gdf file from our personal friend network by clicking on the link named here in the Step 2. Then we will download the GDF (Graph Modeling Language) file. Netvizz will give us the number of nodes and edges (links); finally we will click on the gdf file link, as we can see in the following screenshot: The output file myFacebookNet.gdf will look like this: nodedef>name VARCHAR,label VARCHAR,gender VARCHAR,locale VARCHAR,agerankINT23917067,Jorge,male,en_US,10623931909,Haruna,female,en_US,10535702006,Joseph,male,en_US,104503839109,Damian,male,en_US,103532735006,Isaac,male,es_LA,102. . .edgedef>node1 VARCHAR,node2 VARCHAR23917067,3570200623917067,62939583723917067,74734348223917067,75560507523917067,1186286815. . . In the following screenshot we may see the visualization of the graph (106 nodes and 279 links). The nodes represent my friends and the links represent how my friends are connected between them. Transforming GDF to JSON In order to work with the graph in the web with d3.js, we need to transform our gdf file to json format. Firstly, we need to import the libraries numpy and json. import numpy as npimport json The numpy function, genfromtxt, will obtain only the ID and name from the nodes.csv file using the usecols attribute in the 'object' format. nodes = np.genfromtxt("nodes.csv",dtype='object',delimiter=',',skip_header=1,usecols=(0,1)) Then, the numpy function, genfromtxt, will obtain links with the source node and target node from the links.csv file using the usecols attribute in the 'object' format. links = np.genfromtxt("links.csv",dtype='object',delimiter=',',skip_header=1,usecols=(0,1)) The JSON format used in the D3.js Force Layout graph implemented in this article requires transforming the ID (for example, 100001448673085) into a numerical position in the list of nodes. Then, we need to look for each appearance of the ID in the links and replace them by their position in the list of nodes. for n in range(len(nodes)):for ls in range(len(links)):if nodes[n][0] == links[ls][0]:links[ls][0] = nif nodes[n][0] == links[ls][1]:links[ls][1] = n Now, we need to create a dictionary "data" to store the JSON file. data ={} Next, we need to create a list of nodes with the names of the friends in the format as follows: "nodes": [{"name": "X"},{"name": "Y"},. . .] and add it to thedata dictionary.lst = []for x in nodes:d = {}d["name"] = str(x[1]).replace("b'","").replace("'","")lst.append(d)data["nodes"] = lst Now, we need to create a list of links with the source and target in the format as follows: "links": [{"source": 0, "target": 2},{"source": 1, "target":2},. . .] and add it to the data dictionary.lnks = []for ls in links:d = {}d["source"] = ls[0]d["target"] = ls[1]lnks.append(d)data["links"] = lnks Finally, we need to create the file, newJson.json, and write the data dictionary in the file with the function dumps of the json library. with open("newJson.json","w") as f:f.write(json.dumps(data)) The file newJson.json will look as follows: {"nodes": [{"name": "Jorge"},{"name": "Haruna"},{"name": "Joseph"},{"name": "Damian"},{"name": "Isaac"},. . .],"links": [{"source": 0, "target": 2},{"source": 0, "target": 12},{"source": 0, "target": 20},{"source": 0, "target": 23},{"source": 0, "target": 31},. . .]} Graph visualization with D3.js D3.js provides us with the d3.layout.force() function that use the Force Atlas layout algorithm and help us to visualize our graph. First, we need to define the CSS style for the nodes, links, and node labels. <style>.link {fill: none;stroke: #666;stroke-width: 1.5px;}.node circle{fill: steelblue;stroke: #fff;stroke-width: 1.5px;}.node text{pointer-events: none;font: 10px sans-serif;}</style> Then, we need to refer the d3js library. <script src = "http://d3js.org/d3.v3.min.js"></script> Then, we need to define the width and height parameters for the svg container and include into the body tag. var width = 1100,height = 800var svg = d3.select("body").append("svg").attr("width", width).attr("height", height); Now, we define the properties of the force layout such as gravity, distance, and size. var force = d3.layout.force().gravity(.05).distance(150).charge(-100).size([width, height]); Then, we need to acquire the data of the graph using the JSON format. We will configure the parameters for nodes and links. d3.json("newJson.json", function(error, json) {force.nodes(json.nodes).links(json.links).start(); For a complete reference about the d3js Force Layout implementation, visit the link https://github.com/mbostock/d3/wiki/Force-Layout. Then, we define the links as lines from the json data. var link = svg.selectAll(".link").data(json.links).enter().append("line").attr("class", "link");var node = svg.selectAll(".node").data(json.nodes).enter().append("g").attr("class", "node").call(force.drag); Now, we define the node as circles of size 6 and include the labels of each node. node.append("circle").attr("r", 6);node.append("text").attr("dx", 12).attr("dy", ".35em").text(function(d) { return d.name }); Finally, with the function, tick, run step-by-step the force layout simulation. force.on("tick", function(){link.attr("x1", function(d) { return d.source.x; }).attr("y1", function(d) { return d.source.y; }).attr("x2", function(d) { return d.target.x; }).attr("y2", function(d) { return d.target.y; });node.attr("transform", function(d){return "translate(" + d.x + "," + d.y + ")";})});});</script> In the image below we can see the result of the visualization. In order to run the visualization we just need to open a Command Terminal and run the following Python command or any other web server. >>python –m http.server 8000 Then you just need to open a web browser and type the direction http://localhost:8000/ForceGraph.html. In the HTML page we can see our Facebook graph with a gravity effect and we can interactively drag-and-drop the nodes. All the codes and datasets of this article may be found in the author github repository in the link below.https://github.com/hmcuesta/PDA_Book/tree/master/Chapter10 Summary In this article we developed our own social graph visualization tool with D3js, transforming the data obtained from Netvizz with GDF format into JSON. Resources for Article: Further resources on this subject: GNU Octave: Data Analysis Examples [Article] Securing data at the cell level (Intermediate) [Article] Analyzing network forensic data (Become an expert) [Article]
Read more
  • 0
  • 0
  • 8406

article-image-creating-quizzes
Packt
24 Oct 2013
9 min read
Save for later

Creating Quizzes

Packt
24 Oct 2013
9 min read
(For more resources related to this topic, see here.) Creating a short-answer question For this task, we will create a card to host an interface for a short-answer question. This type of question allows the user to input their answers via the keyboard. Evaluating this type of answer can be especially challenging, since there could be several correct answers and users are prone to make spelling mistakes. Engage Thrusters Create a new card and name it SA. Copy the Title label from the Main card and paste it onto the new SA card. This will ensure the title label field has a consistent format and location. Copy the Question label from the TF card and paste it onto the new SA card. Copy the Progress label from the TF card and paste it onto the new SA card. Copy the Submit button from the Sequencing card and paste it onto the new SA card. Drag a text entry field onto the card and make the following modifications: Change the name to answer. Set the size to 362 by 46. Set the location to 237, 185. Change the text size to 14. We are now ready to program our interface. Enter the following code at the card level: on preOpenCard global qNbr, qArray # Section 1 put 1 into qNbr # Section 2 put "" into fld "question" put "" into fld "answer" put "" into fld "progress" # Section 3 put "What farm animal eats shrubs, can be eaten, and are smaller than cows?" into qArray["1"]["question"] put "goat" into qArray["1"]["answer"] -- put "What is used in pencils for writing?" into qArray["2"]["question"] put "lead" into qArray["2"]["answer"] -- put "What programming language are you learning" into qArray["3"] ["question"] put "livecode" into qArray["3"]["answer"] end preOpenCard In section 1 of this code, we reset the question counter (qNbr) variable to 1. Section 2 contains the code to clear the question, answer, and progress fields. Section 3 populates the question/answer array (qArray). As you can see, this is the simplest array we have used. It only contains a question and answer pairing for each row. Our last step for the short answer question interface is to program the Submit button. Here is the code for that button: on mouseUp global qNbr, qArray local tResult # Section 1 if the text of fld "answer" contains qArray[qNbr]["answer"] then put "correct" into tResult else put "incorrect" into tResult end if #Section 2 switch tResult case "correct" if qNbr < 3 then answer "Very Good." with "Next" titled "Correct" else answer "Very Good." with "Okay" titled "Correct" end if break case "incorrect" if qNbr < 3 then answer "The correct answer is: " & qArray[qNbr]["answer"] & "." with "Next" titled "Wrong Answer" else answer "The correct answer is: " & qArray[qNbr]["answer"] & "." with "Okay" titled "Wrong Answer" end if break end switch # Section 3 if qNbr < 3 then add 1 to qNbr nextQuestion else go to card "Main" end if end mouseUp Our Submit button script is divided into three sections. The first section (section 1) checks to see if the answer contained in the array (qArray) is part of the answer the user entered. This is a simple string comparison and is not case sensitive. Section 2 of this button's code contains a switch statement based on the local variable tResult. Here, we provide the user with the actual answer if they do not get it right on their own. The final section (section 3) navigates to the next question or to the main card, depending upon which question set the user is on. Objective Complete - Mini Debriefing We have successfully coded our short answer quiz card. Our approach was to use a simple question and data input design with a Submit button. Your user interface should resemble the following screenshot: Creating a picture question card Using pictures as part of a quiz, poll, or other interface can be fun for the user. It might also be more appropriate than simply using text. Let's create a card that uses pictures as part of a quiz. Engage Thrusters Create a new card and name it Pictures. Copy the Title label from the Main card and paste it onto the new Pictures card. This will ensure the title label field has a consistent format and location. Copy the Question label from the TF card and paste it onto the new Pictures card. Copy the Progress label from the TF card and paste it onto the new Pictures card. Drag a Rectangle Button onto the card and make the following customizations: Change the name to picture1. Set the size to 120 x 120. Set the location to 128, 196. Drag a second Rectangle Button onto the card and make the following customizations: Change the name to picture2. Set the size to 120 x 120. Set the location to 336, 196. Upload the following listed files into your mobile application's Image Library. This LiveCode function is available by selecting the Development pull-down menu, then selecting Image Library. Near the bottom of the Image Library dialog is an Import File button. Once your files are uploaded, take note of the ID numbers assigned by LiveCode: q1a1.png q1a2.png q2a1.png q2a2.png q3a1.png q3a2.png With our interface fully constructed, we are now ready to add LiveCode script to the card. Here is the code you will enter at the card level: on preOpenCard global qNbr, qArray # Section 1 put 1 into qNbr set the icon of btn "picture1" to empty set the icon of btn "picture2" to empty # Section 2 put "" into fld "question" put "" into fld "progress" # Section 3 put "Which puppy is real?" into qArray["1"]["question"] put "2175" into qArray["1"]["pic1"] put "2176" into qArray["1"]["pic2"] put "q1a1" into qArray["1"]["answer"] -- put "Which puppy looks bigger?" into qArray["2"]["question"] put "2177" into qArray["2"]["pic1"] put "2178" into qArray["2"]["pic2"] put "q2a2" into qArray["2"]["answer"] -- put "Which scene is likely to make her owner more upset?" into qArray["3"]["question"] put "2179" into qArray["3"]["pic1"] put "2180" into qArray["3"]["pic2"] put "q3a1" into qArray["3"]["answer"] end preOpenCard In section 1 of this code, we set the qNbr to 1. This is our question counter. We also ensure that there is no image visible in the two buttons. We do this by setting the icon of the buttons to empty. In section 2, we empty the contents of the two onscreen fields (Question and Progress). In the third section, we populate the question set array (qArray). Each question has an answer that corresponds with the filename of the images you added to your stack in the previous step. The ID numbers of the six images you uploaded are also added to the array, so you will need to refer to your notes from step 7. Our next step is to program the picture1 and picture2 buttons. Here is the code for the picture1 button: on mouseUp global qNbr, qArray # Section 1 if qArray[qNbr]["answer"] contains "a1" then if qNbr < 3 then answer "Very Good." with "Next" titled "Correct" else answer "Very Good." with "Okay" titled "Correct" end if else if qNbr < 3 then answer "That is not correct." with "Next" titled "Wrong Answer" else answer "That is not correct." with "Okay" titled "Wrong Answer" end if end if # Section 2 if qNbr < 3 then add 1 to qNbr nextQuestion else go to card "Main" end if end mouseUp In section 1 of our code, we check to see if the answer from the array contains a1, which indicates that the picture on the left is the correct answer. Based on the answer evaluation, one of two text feedbacks is provided to the user. The name of the button on the feedback dialog is either Next or Okay, depending upon which question set the user is currently on. The second section of this code routes the user to either the main card (if they finished all three questions) or to the next question. Copy the code you entered in the picture1 button and paste it onto the picture2 button. Only one piece of code needs to change. On the first line of the section 1 code, change the string from a1 to a2. That line of code should be as follows: if qArray[qNbr]["answer"] contains "a2" then Objective Complete - Mini Debriefing In just 9 easy steps, we created a picture-based question type that uses images we uploaded to our stack's image library and a question set array. Your final interface should look similar to the following screenshot: Adding navigational scripting In this task, we will add scripts to the interface buttons on the Main card. Engage Thrusters Navigate to the Main card. Add the following script to the true-false button: on mouseUp set the disabled of me to true go to card "TF" end mouseUp Add the following script to the m-choice button: on mouseUp set the disabled of me to true go to card "MC" end mouseUp Add the following script to the sequence button: on mouseUp set the disabled of me to true go to card "Sequencing" end mouseUp Add the following script to the short-answer button: on mouseUp set the disabled of me to true go to card "SA" end mouseUp Add the following script to the pictures button: on mouseUp set the disabled of me to true go to card "Pictures" end mouseUp The last step in this task is to program the Reset button. Here is the code for that button: on mouseUp global theScore, totalQuestions, totalCorrect # Section 1 set the disabled of btn "true-false" to false set the disabled of btn "m-choice" to false set the disabled of btn "sequence" to false set the disabled of btn "short-answer" to false set the disabled of btn "pictures" to false # Section 2 set the backgroundColor of grc "progress1" to empty set the backgroundColor of grc "progress2" to empty set the backgroundColor of grc "progress3" to empty set the backgroundColor of grc "progress4" to empty set the backgroundColor of grc "progress5" to empty # Section3 put 0 into theScore put 0 into totalQuestions put 0 into totalCorrect put theScore & "%" into fld "Score" end mouseUp There are three sections to this code. In section 1, we are enabling each of the buttons. In the second section, we are clearing out the background color of each of the five progress circles in the bottom-center of the screen. In the final section, section 3, we reset the score and the score display. Objective Complete - Mini Debriefing That is all there was to this task, seven easy steps. There are no visible changes to the mobile application's interface. Summary In this article, we saw how to create a couple of quiz apps for mobile such as short-answer questions and picture card questions. Resources for Article: Further resources on this subject: Creating and configuring a basic mobile application [Article] Creating mobile friendly themes [Article] So, what is XenMobile? [Article]
Read more
  • 0
  • 0
  • 8094
article-image-improving-your-development-speed
Packt
23 Oct 2013
7 min read
Save for later

Improving Your Development Speed

Packt
23 Oct 2013
7 min read
(For more resources related to this topic, see here.) What all developers want is to do their job as fast as they can without sacrificing the quality of their work. IntelliJ has a large range of features that will reduce the time spent in development. But, to achieve the best performance that IntelliJ can offer, it is important that you understand the IDE and adapt some of your habits. In this article, we will navigate through the features that can help you do your job even faster. You will understand IntelliJ's main elements and how they work, and beyond this, learn how IntelliJ can help you organize your activities and the files you are working on. To further harness IntelliJ's abilities, you will also learn how to manage plugins and see a short list of plugins that can help you. Identifying and understanding window elements Before we start showing you techniques you can use to improve your performance using IntelliJ, you need to identify and understand the visual elements present in the main window of the IDE. Knowing these elements will help you find what you want faster. The following screenshot shows the IntelliJ main window: The main window can be divided into seven parts as shown in the previous screenshot: The main menu contains options that you can use to do tasks such as creating projects, refactoring, managing files in version control, and more. The main toolbar element contains some essential options. Some buttons are shown or hidden depending on the configuration of the project; version control buttons are an example of this. The Navigation Bar is sometimes a quick and good alternative to navigate easily and fast through the project files. Tool tabs are shown on both sides of the screen and at the bottom of IntelliJ. They represent the tools that are available for the project. Some tabs are available only when facets are enabled in the project (e.g. the Persistence tab). When the developer clicks on a tool tab, a window appears. These windows will present the project in different perspectives. The options available in each tool window will provide the developer with a wide range of development tasks. The editor is where you can write your code. The Status Bar indicates the current IDE state and provides some options to manipulate the environment. For example, you can hide the tool tabs by clicking on the icon at the bottom-left of the window. In almost all elements, there are context menus available. These menus will provide extra options that may complement and ease your work. For example, the context menu, available in the tool bar, provides an option to hide itself and another to customize the menu and toolbars. You will notice that some tool tabs have numbers. These numbers are used in conjunction with the Alt key to access the tool window you want quickly, Alt + 1, for example, will open the Project tool window. Each tool window will have different options; some will present search facilities, others will show specific options. They use a common structure: a title bar, a toolbar, and the content pane. Some tool windows don't have a toolbar and, in others, the options in the title bar may vary. However, all of them will have at least two buttons in the rightmost part of the title bar: a gear and a small bar with an arrow. The first button is used to configure some properties of the tool and the second will just minimize the window. The following screenshot shows some options in the Database tool: The options available under the gear button icon generally differ from tool to tool. However, in the drop-down list, you will find four common options: Pinned, Docked, Floating, and Split modes. As you may have already imagined, these options are used to define how the tool window will be shown. The Pinned mode is very useful when it is unmarked; using this, when you focus on code editor you don't lose time minimizing the tool window. Identifying and understanding code editor elements The editor provides some elements that can facilitate navigation through the code and help identify problems in it. In the following screenshot, you can see how the editor is divided: The editor area, as you probably know, is where you edit your source code. The gutter area is where different types of information about the code is shown, simply using icons or special marks like breakpoints and ranges. The indicators used here aren't used to just display information; you can perform some actions depending on the indicator, such as reverting changes or navigating through the code. The smart completion popup, as you've already seen, provides assistance to the developer in accordance with the current context. The document tabs area is where the tabs of each opened document are available. The type of document is identified by an icon and the color in the name of the file shows its status in version control: blue stands for "modified", green for "new", red for "not in VCS", and black for "not changed". This component has a context menu that provides some other facilities as well. The marker bar is positioned to the right-hand side of the IDE and its goal is to show the current status of the code. At the top, the square mark can be green for when your code is OK, yellow for warnings that are not critical, and red for compilation errors, respectively. Below the square situated on top of the IDE this element can have other colored marks used to help the developer go directly to the desired part of the code. Sometimes, while you are coding, you may notice a small icon floating near the cursor; this icon represents that there are some intentions available that could help you: indicates that IntelliJ proposes a code modification that isn't totally necessary. It covers warning corrections to code improvement. indicates an intention action that can be used but doesn't provide any improvement or code correction. indicates there is a quick fix available to correct an eminent code error. indicates that the alert for the intention is disabled but the intention is still available. The following figure shows the working intention: Intention actions can be grouped in four categories listed as follows: Create from usage is the kind of intention action that proposes the creation of code depending on the context. For example, if you enter a method name that doesn't exist, this intention will recognize it and propose the creation of the method. Quick fixes is the type of intention that responds to code mistakes, such as wrong type usage or missing resources. Micro refactoring is the kind of intention that is shown when the code is syntactically correct; however, it could be improved (for readability for example). Fragment action is the type of intention used when there are string literals of an injected language; this type of injection can be used to permit you to edit the corresponding sentence in another editor. Intention actions can be enabled or disabled on-the-fly or in the Intention section in the configuration dialog; by default, all intentions come activated. Adding intentions is possible only after installing plugins for them or creating your own plugin. If you prefer, you can use the Alt + Enter shortcut to invoke the intentions popup. Summary As you have seen in this article, IntelliJ provides a wide range of functionalities that will improve your development speed. More important than knowing all the shortcuts IntelliJ offers, is to understand what is possible do with them and when to use a feature. Resources for Article: Further resources on this subject: NetBeans IDE 7: Building an EJB Application [Article] JBI Binding Components in NetBeans IDE 6 [Article] Smart Processes Using Rules [Article]
Read more
  • 0
  • 0
  • 4391

article-image-taking-control-reactivity-inputs-and-outputs
Packt
23 Oct 2013
7 min read
Save for later

Taking Control of Reactivity, Inputs, and Outputs

Packt
23 Oct 2013
7 min read
(For more resources related to this topic, see here.) Showing and hiding elements of the UI We'll start easy with a simple function that you are certainly going to need if you build even a moderately complex application. Those of you who have been doing extra credit exercises and/or experimenting with your own applications will probably have already wished for this or, indeed, have already found it. conditionalPanel() allows you to show/hide UI elements based on other selections within the UI. The function takes a condition (in JavaScript, but the form and syntax will be familiar from many languages) and a UI element, and displays the UI only when the condition is true. This is actually used a couple of times in the advanced GA application and indeed in all the applications I've ever written of even moderate complexity. The following is a simpler example (from ui.R, of course, in the first section, within sidebarPanel()), which allows users who request a smoothing line to decide what type they want: conditionalPanel(condition = "input.smoother == true",selectInput("linearModel", "Linear or smoothed",list("lm", "loess"))) As you can see, the condition appears very R/Shiny-like, except with the "." operator familiar to JavaScript users in place of "$", and with "true" in lower case. This is a very simple but powerful way of making sure that your UI is not cluttered with irrelevant material. Giving names to tabPanel elements In order to further streamline the UI, we're going to hide the hour selector when the monthly graph is displayed and the date selector when the hourly graph is displayed. The difference is illustrated in the following screenshot with side-by-side pictures, hourly figures UI on the left-hand side and monthly figures on the right-hand side: In order to do this, we're going to have to first give the tabs of the tabbed output names. This is done as follows (with the new code in bold): tabsetPanel(id ="theTabs",tabPanel("Summary", textOutput("textDisplay"),value = "summary"),tabPanel("Monthly figures",plotOutput("monthGraph"), value = "monthly"),tabPanel("Hourly figures",plotOutput("hourGraph"), value = "hourly")) As you can see, the whole panel is given an ID (theTabs), and then each tabPanel is also given a name (summary, monthly, and hourly). They are referred to in the server.R file very simply as input$theTabs. Let's have a quick look at a chunk of code in server.R that references the tab names; this code makes sure that we subset based on date only when the date selector is actually visible, and by hour only when the hour selector is actually visible. Our function to calculate and pass data now looks like the following (new code again bolded): passData <- reactive({if(input$theTabs != "hourly"){analytics <- analytics[analytics$Date %in%seq.Date(input$dateRange[1], input$dateRange[2],by = "days"),]}if(input$theTabs != "monthly"){analytics <- analytics[analytics$Hour %in%as.numeric(input$minimumTime) :as.numeric(input$maximumTime),]}analytics <- analytics[analytics$Domain %in%unlist(input$domainShow),]analytics}) As you can see, subsetting by month is carried out only when the date display is visible (that is, when the hourly tab is not shown), and vice versa. Finally, we can make our changes to ui.R to remove parts of the UI based on tab selection: conditionalPanel(condition = "input.theTabs != 'hourly'",dateRangeInput(inputId = "dateRange",label = "Date range",start = "2013-04-01",max = Sys.Date())),conditionalPanel(condition = "input.theTabs != 'monthly'",sliderInput(inputId = "minimumTime",label = "Hours of interest- minimum",min = 0,max = 23,value = 0,step = 1),sliderInput(inputId = "maximumTime",label = "Hours of interest- maximum",min = 0,max = 23,value = 23,step = 1)) Note the use in the latter example of two UI elements within the same conditionalPanel() call; it is worth noting that it helps you keep your code clean and easy to debug. Reactive user interfaces Another trick you will definitely want up your sleeve at some point is a reactive user interface. This enables you to change your UI (for example, the number or content of radio buttons) based on reactive functions. For example, consider an application that I wrote related to survey responses across a broad range of health services in different areas. The services are related to each other in quite a complex hierarchy, and over time, different areas and services respond (or cease to exist, or merge, or change their name...), which means that for each time period the user might be interested in, there would be a totally different set of areas and services. The only sensible solution to this problem is to have the user tell you which area and date range they are interested in and then give them back the correct list of services that have survey responses within that area and date range. The example we're going to look at is a little simpler than this, just to keep from getting bogged down in too much detail, but the principle is exactly the same and you should not find this idea too difficult to adapt to your own UI. We are going to imagine that your users are interested in the individual domains from which people are accessing the site, rather than just have them lumped together as the NHS domain and all others. To this end, we will have a combo box with each individual domain listed. This combo box is likely to contain a very high number of domains across the whole time range, so we will let users constrain the data by date and only have the domains that feature in that range return. Not the most realistic example, but it will illustrate the principle for our purposes. Reactive user interface example – server.R The big difference is that instead of writing your UI definition in your ui.R file, you place it in server.R, and wrap it in renderUI(). Then all you do is point to it from your ui.R file. Let's have a look at the relevant bit of the server.R file: output$reacDomains <- renderUI({domainList = unique(as.character(passData()$networkDomain))selectInput("subDomains", "Choose subdomain", domainList)}) The first line takes the reactive dataset that contains only the data between the dates selected by the user and gives all the unique values of domains within it. The second line is a widget type we have not used yet which generates a combo box. The usual id and label arguments are given, followed by the values that the combo box can take. This is taken from the variable defined in the first line. Reactive user interface example – ui.R The ui.R file merely needs to point to the reactive definition as shown in the following line of code (just add it in to the list of widgets within sidebarPanel()): uiOutput("reacDomains") You can now point to the value of the widget in the usual way, as input$subDomains. Note that you do not use the name as defined in the call to renderUI(), that is, reacDomains, but rather the name as defined within it, that is, subDomains. Summary It's a relatively small but powerful toolbox with which you can build a vast array of useful and intuitive applications with comparatively little effort. This article looked at fine-tuning the UI using conditionalPanel() and observe(), and changing our UI reactively. Resources for Article: Further resources on this subject: Fine Tune the View layer of your Fusion Web Application [Article] Building tiny Web-applications in Ruby using Sinatra [Article] Spring Roo 1.1: Working with Roo-generated Web Applications [Article]
Read more
  • 0
  • 0
  • 3356

article-image-working-audio
Packt
23 Oct 2013
9 min read
Save for later

Working with Audio

Packt
23 Oct 2013
9 min read
(For more resources related to this topic, see here.) Planning the audio In Camtasia Studio, we can stack multiple audio tracks on top of each other. While this is a useful and powerful way to build a soundtrack, it can lead to a cluttered audio output if we do not plan ahead. Audio tracks can be used for a wide range of purposes. It's best to storyboard audio to avoid creating a confusing audio mix. If we consider how each audio track will be used before we begin to overlay each file on the timeline, we can visualize the end result and resist the temptation to layer too many audio effects on top of each other. The importance of consistency Producing professional video in Camtasia Studio comes down to consistency and detail. The more consistent we are, the more professional the result will be. The more we pay attention to detail, the more professional the result is. By being consistent in our use of audio effects, we can avoid creating unintentional distractions or misleading the viewer. For example, if we choose to use a ping sound to represent a mouse click, we should make sure that all mouse clicks use the same ping sound so that the viewer understands and associates the sound with the action. A note on background music When deciding what audio we want in our video, we should always think about our target audience and the type of message we are trying to deliver. Never use background music unless it adds to the video content. For example, background music can be a useful way of engaging our viewer, but if we are delivering an important health and safety message, or delivering a quiz, a backing track may be distracting. If our audience are the staff in customer-facing departments, we may not want to include audio tracks at all. We wouldn't want the sound from our videos to be audible to a customer. Types of audio There are three main types of audio we can add to our video: Voice-over tracks Background music Sound effects Preparing to record a voice-over Various factors affect the quality and consistency of voice-over recordings. In Camtasia Studio, we can add effects but it's best to get the source audio right in the first instance. The factors are given as follows: We often don't pay attention to the qualities and tones in our own voices, but they can and do change. From day to day, your tone of voice can subtly change. Air temperature, illness, or mood can affect the way your voice sounds in a recording. In addition, the environment we use to record a voice-over can have a dramatic effect on the end result. Some rooms will give your voice natural reverb; others will sound very dead. The equipment we use will affect the recording. For example, different microphones will produce different results. When we prepare for a voice-over recording, we must aim to keep our voice, environment, and equipment as stable and consistent as possible. That means we should aim to record the voice-over in one session so that we can control all these factors. We may choose a different person to provide the voice-over. Again, we should take a consistent approach in how we use their voice. Voice-over recording is always a long process and involves trial, error, and multiple takes. We should allow more time than we feel is strictly necessary. Many recordings inevitably overrun. If any sections of the recording are questionable, we should aim to record all of the alternatives in the same session for a seamless result. The studio environment Most Camtasia Studio users do not have access to a professional recording studio. This need not be a problem. We can use practically any quiet room to record our voice-over, although there are some basic pointers that will improve the result. When choosing a studio location, consider the following: Ambient noise: Try to record in quiet environment. If we can use an empty room where there are no passers by or devices making any noise, this will make our recording clearer. Choose a room away from potential sources of noise (busy corridors, main roads, and so on). Noise leakage: Ensure that any doors and windows are closed to minimize noise pollution from outside the room and outside the building. Equipment noise: Ensure that all unnecessary programs on the PC are closed to prevent any unwanted sounds or alerts. End any background tasks, such as email checkers or task schedulers, and ensure any instant messaging software is closed or in offline mode. Positioning: Experiment with placing the microphone in different places around the room. The acoustics of a room can greatly affect the quality of a recording and taking time to find the best place for the microphone will help. For efficiency, we can test the audio quality quickly by wearing headphones while speaking into the microphone. Consider posture: Standing up opens up the diaphragm and improves the sound of our voice when we record. Avoid recording while seated, and hold any notes or papers at eye level to maintain a constant tone. Using scripts When it comes to voice-over recording, a well-prepared script is the most important piece of preparation we can do. Working from a script is far simpler than attempting to make up our narration as we go along. It helps to maintain a good pace in the video and greatly reduces the need for multiple takes, making recording far more efficient. Creating a script need not be time-consuming. If we have already planned out and recorded our video track, writing a script will be far simpler. Writing an effective script The script you write should support the action in the video and maintain a healthy pace. There are a number of tips we can bear in mind to do this. These tips are given as follows: Sync audio with video: Plan the script to coincide with any actions we take in the video. This may mean incorporating pauses into the script to allow a certain on-screen action to complete. Be flexible: We may need to go back and lengthen a section of video to incorporate the voice-over and explanation. It is better to do this than rush the voice-over and attempt to force it to fit. Use basic copywriting techniques: We should consider the message in the video and use the appropriate style. For example, if we are describing a process, we would want to use the active voice. In an internal company update, we may want to adopt a more conversational tone. Be direct and concise: A short and simple statement is far easier to process than a long, drawn out argument. We should always test our script prior to the recording session. We should also be prepared to re-write and hone the content. Reading a script aloud is a useful way of estimating its length and picking out any awkward phrases that do not flow. We will save time if we perfect the script before we sit down in front of the microphone. Recording equipment Most laptop computers have a built in microphone, as do some desktop computers. While these microphones are perfectly adequate for video or audio chats and other casual uses, we should not use them to create Camtasia Studio recordings. Although the quality may be good, and the audio may be clear, these microphones often pick up a large amount of ambient noise, such as the fans inside the computer. Additionally, the audio captured using built-in microphones often require processing and amplification, which can degrade its quality. Camtasia Studio has a range of editing tools that can help you to tweak your audio recording. However, processing should always be a last resort. The more we use a tool to process our voice-over, the more the source material is prone to being distorted. If we have better quality source material, we will not need to rely on these features; this will make the editing process much simpler. When working in Camtasia Studio, it is preferable to invest in a good quality external microphone. Basic microphones are inexpensive and offer considerably better audio recording than built-in microphones. Choosing a microphone External microphones are very affordable. Unless you have specific need for a professional-standard microphone, we recommend a USB microphone. Many of these microphones are sold as podcasting microphones and are perfectly adequate for use in Camtasia Studio. There are two main types of external microphone: Consider a lapel microphone if you plan to operate the computer as you record or present to the camera while you are speaking. Lapel microphones clip on to your clothing and leave your hands free. If you are more comfortable working at a desk, a microphone with a sturdy tripod stand will be a good investment. An external microphone with built in noise cancellation can give us a degree of control at the recording stage, rather than having to edit out noise later. A good stand will give us a greater degree of flexibility when it comes to microphone placement. How to set up an external microphone We can set up the external microphone before we begin recording by following the given steps: Navigate to Tools | Voice Narration. The Voice Narration screen is displayed. Click on Audio setup wizard.... The Audio Setup Wizard screen is displayed. Select the Audio device, as shown in the following screenshot. Summary In this article, we have looked at a range of ways to improve the quality of the audio in our Camtasia Studio projects. We have considered voice-over recording techniques, equipment, editing, sound effects, and background music. Resources for Article: Further resources on this subject: Editing attributes [Article] Basic Editing [Article] Video Editing in Blender using Video Sequence Editor: Part 1 [Article]
Read more
  • 0
  • 0
  • 3523
article-image-setting-slick2d
Packt
23 Oct 2013
4 min read
Save for later

Setting Up Slick2D

Packt
23 Oct 2013
4 min read
(For more resources related to this topic, see here.) What is Slick2D? Slick2D is a multi-platform library for two dimensional game development that sits upon the LWJGL(Light-Weight Java Game Library). Slick2D simplifies the processes of game development such as game loop, rendering, updating, frame setup, and state-based game creation. It also offers some features that LWJGL does not, such as particle emitters and integration with Tiled (a map editor). Developers of all skill levels can enjoy Slick2D, as it offers a degree of simplicity that you can't find in most libraries. This simplicity not only makes it a great library for programmers but artists as well, who may not have the technical knowledge to create games in other libraries. Downloading the Slick2D and LWJGL files The Slick2D and LWJGL jar files, plus the LWJGL native files, are needed to create a Slick2D game project. The only system requirement for Slick2D is a Java JDK. To get the files, we perform the following steps: Obtaining the LWJGL files: Navigate to http://www.lwjgl.org/download.php. Download the most recent stable build. The .zip file will include both the LWJGL jar file and the native files. (This .zip file will be referenced as lwjgl.zip file.) Obtaining the Slick2D files: Due to hosting issues, the Slick2D files are being hosted by a community member at http://slick.ninjacave.com. If this site is not available, follow the alternative instructions at step 3. Click on Download. Alternative method of obtaining the Slick2D files: Navigate to https://bitbucket.org/kevglass/slick. Download the source. Build the ant script located at slick/trunk/Slick/build.xml Build it in eclipse or command line using $ ant. Setting up an eclipse project We will utilize the Eclipse IDE that can be found at http://www.eclipse.org/ when working with Slick2D in this article. You may, however, utilize other options. Perform the following these steps to set up a Slick2D project: Navigate to File | New | Java Project. Name your project and click on Finish. Create a new folder in your project and name it lib. Add two subfolders named jars and native. Place both lwjgl.jar and slick.jar in the jars subfolder inside our eclipse project. Take all the native files from lwjgl.zip and place them in the native subfolder. Copy the contents of the subfolders inside native from lwjgl.zip not the subfolders themselves. Right-click on project then click on Properties. Click on Java Build Path and navigate to the Libraries tab. Add both the jars from the project. Select and expand lwjgl.jar from the Libraries tab and click on Native library location: (None) then click on Edit and search the workspace for the native's folder. Native files The native files included in lwjgl.zip are platform-specific libraries that allow the developers to make one game that will work on all of the different platforms. What if I want my game to be platform-specific? No real benefit exists to being platform-specific with Slick2D. In the foregoing tutorial, we will establish a game as a multi-platform game. However, if you want your game to be platform-specific, you can make it platform-specific. In the previous tutorial (step 6) we took the content of each operating system's folder and put that content into our native folder. If, instead, you desire to make your game platform-specific, then instead of copying the contents of these folders, you would copy the entire folder as illustrated as follows: When defining the natives for LWJGL (step 10 in previous example), simply point towards the operating system of your choice. Summary In this article we learned tons of important things necessary to create a project in Slick2D. So far we covered: Downloading the necessary library files Setting up a project (platform-specific or multi-platform) Native files Resources for Article: Further resources on this subject: HTML5 Games Development: Using Local Storage to Store Game Data [Article] Adding Sound, Music, and Video in 3D Game Development with Microsoft Silverlight 3: Part 2 [Article] Adding Finesse to Your Game [Article]
Read more
  • 0
  • 0
  • 13410

article-image-basic-concepts
Packt
23 Oct 2013
12 min read
Save for later

Basic Concepts

Packt
23 Oct 2013
12 min read
  (For more resources related to this topic, see here.) Scene and Actors You must have heard the quote written by William Shakespeare: "All the world's a stage, and all the men and women merely players: they have their exits and their entrances; and one man in his time plays many parts, his acts being seven ages." As per my interpretation, he wanted to say that this world is like a stage, and human beings are like players or actors who perform our role in it. Every actor may have his own discrete personality and influence, but there is only one stage, with a finite area, predefined props, and lighting conditions. In the same way, a world in PhysX is known as scene and the players performing their role are known as actors. A scene defines the property of the world in which a simulation takes place, and its characteristics are shared by all of the actors created in the scene. A good example of a scene property is gravity, which affects all of the actors being simulated in a scene. Although different actors can have different properties, independent of the scene. An instance of a scene can be created using the PxScene class. An actor is an object that can be simulated in a PhysX scene. It can have properties, such as shape, material, transform, and so on. An actor can be further classified as a static or dynamic actor; if it is a static one, think of it as a prop or stationary object on a stage that is always in a static position, immovable by simulation; if it is dynamic, think of it as a human or any other moveable object on the stage that can have its position updated by the simulation. Dynamic actors can have properties like mass, momentum, velocity, or any other rigid body related property. An instance of static actor can be created by calling PxPhysics::createRigidStatic() function, similarly an instance of dynamic actor can be created by calling PxPhysics::createRigidDynamic() function. Both functions require single parameter of PxTransform type, which define the position and orientation of the created actor. Materials In PhysX, a material is the property of a physical object that defines the friction and restitution property of an actor, and is used to resolve the collision with other objects. To create a material, call PxPhysics::createMaterial(), which requires three arguments of type PxReal; these represent static friction, dynamic friction and restitution, respectively. A typical example for creating a PhysX material is as follows: PxMaterial* mMaterial = gPhysicsSDK->createMaterial(0.5,0.5,0.5); Static friction represents the friction exerted on a rigid body when it is in a rest position, and its value can vary from 0 to infinity. On the other hand, dynamic friction is applicable to a rigid body only when it is moving, and its value should always be within 0 and 1. Restitution defines the bounciness of a rigid body and its value should always be between 0 and 1; the body will be more bouncy the closer its value is to 1. All of these values can be tweaked to make an object behave as bumpy as a Ping-Pong ball or as slippery as ice when it interacts with other objects. Shapes When we create an actor in PhysX, there are some other properties, like its shape and material, that need to be defined and used further as function parameters to create an actor. A shape in PhysX is a collision geometry that defines the collision boundaries for an actor. An actor can have more than one shape to define its collision boundary. Shapes can be created by calling PxRigidActor::createShape(), which needs at least one parameter each of type PxGeometry and PxMaterial respectively. A typical example of creating a PhysX shape of an actor is as follows: PxMaterial* mMaterial = gPhysicsSDK->createMaterial(0.5,0.5,0.5); PxRigidDynamic* sphere = gPhysicsSDK->createRigidDynamic(spherePos); sphere->createShape(PxSphereGeometry(0.5f), *mMaterial); An actor of type PxRigidStatic, which represents static actors, can have shapes such as a sphere, capsule, box, convex mesh, triangular mesh, plane, or height field. Permitted shapes for actors of the PxRigidDynamic type that represents dynamic actors depends on whether the actor is flagged as kinematic or not. If the actor is flagged as kinematic, it can have all of the shapes of an actor of the PxRigidStatic type; otherwise it can have shapes such as a sphere, capsule, box, convex mesh, but not a triangle mesh, a plane, or a height field. Creating the first PhysX 3 program Now we have enough understanding to create our first PhysX program. In this program, we initialize PhysX SDK, create a scene, and then add two actors. The first actor will be a static plane that will act as a static ground, and the second will be a dynamic cube positioned a few units above the plane. Once the simulation starts, the cube should fall on to the plane under the effect of gravity. Because this is our first PhysX code, to keep it simple, we will not draw any actor visually on the screen. We will just print the position of the falling cube on the console until it comes to rest. We will start our code by including the required header files. PxPhysicsAPI.h is the main header file for PhysX, and includes the entire PhysX API in a single header. Later on, you may want to selectively include only the header files that you need, which will help to reduce the application size. We also load the three most frequently used precompiled PhysX libraries for both the Debug and Release platform configuration of VC++ 2010 Express compiler shown as follows: In addition to the std namespace, which is a part of standard C++, we also need to add the physx namespace for PhysX, as follows: #include <iostream> #include <PxPhysicsAPI.h> //PhysX main header file //-------Loading PhysX libraries----------] #ifdef _DEBUG #pragma comment(lib, "PhysX3DEBUG_x86.lib") #pragma comment(lib, "PhysX3CommonDEBUG_x86.lib") #pragma comment(lib, "PhysX3ExtensionsDEBUG.lib") #else #pragma comment(lib, "PhysX3_x86.lib") #pragma comment(lib, "PhysX3Common_x86.lib") #pragma comment(lib, "PhysX3Extensions.lib") #endif using namespace std; using namespace physx; Initializing PhysX For initializing PhysX SDK, we first need to create an object of type PxFoundation by calling the PxCreateFoundation() function. This requires three parameters: the version ID, an allocator callback, and an error callback. The first parameter prevents a mismatch between the headers and the corresponding SDK DLL(s). The allocator callback and error callback are specific to an application, but the SDK also provides a default implementation, which is used in our program. The foundation class is needed to initialize higher-level SDKs. The code snippet for creating a foundation of PhysX SDK is as follows: static PxDefaultErrorCallback gDefaultErrorCallback; static PxDefaultAllocator gDefaultAllocatorCallback; static PxFoundation* gFoundation = NULL; //Creating foundation for PhysX gFoundation = PxCreateFoundation (PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback); After creating an instance of the foundation class, we finally create an instance of PhysX SDK by calling the PxCreatePhysics() function. This requires three parameters: the version ID, the reference of the PxFoundation object we created earlier, and PxTolerancesScale. The PxTolerancesScale parameter makes it easier to author content on different scales and still have PhysX work as expected; however, to get started, we simply pass a default object of this type. We make sure that the PhysX device is created correctly by comparing it with NULL. If the object is not equal to NULL, the device was created successfully. The code snippet for creating an instance of PhysX SDK is as follows: static PxPhysics* gPhysicsSDK = NULL; //Creating instance of PhysX SDK gPhysicsSDK = PxCreatePhysics (PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale() ); if(gPhysicsSDK == NULL) { cerr<<"Error creating PhysX3 device, Exiting..."<<endl; exit(1); } Creating scene Once the PhysX device is created, it's time to create a PhysX scene and then add the actors to it. You can create a scene by calling PxPhysics::createScene(), which requires an instance of the PxSceneDesc class as a parameter. The object of PxSceneDesc contains the description of the properties that are required to create a scene, such as gravity. The code snippet for creating an instance of the PhysX scene is given as follows: PxScene* gScene = NULL; //Creating scene PxSceneDesc sceneDesc(gPhysicsSDK->getTolerancesScale()); sceneDesc.gravity = PxVec3(0.0f, -9.8f, 0.0f); sceneDesc.cpuDispatcher = PxDefaultCpuDispatcherCreate(1); sceneDesc.filterShader = PxDefaultSimulationFilterShader; gScene = gPhysicsSDK->createScene(sceneDesc); Then, one instance of PxMaterial is created, which will be used as a parameter for creating the actors. //Creating material PxMaterial* mMaterial = //static friction, dynamic friction, restitution gPhysicsSDK->createMaterial(0.5,0.5,0.5); Creating actors Now it's time to create actors; our first actor is a plane that will act as a ground. When we create a plane in PhysX, its default orientation is vertical, like a wall, but we want it to act like a ground. So, we have to rotate it by 90 degrees so that its normal will face upwards. This can be done using the PxTransform class to position and rotate the actor in 3D world space. Because we want to position the plane at the origin, we put the first parameter of PxTransform as PxVec3(0.0f,0.0f,0.0f); this will position the plane at the origin. We also want to rotate the plane along the z-axis by 90 degrees, so we will use PxQuat(PxHalfPi,PxVec3(0.0f,0.0f,1.0f)) as the second parameter. Now we have created a rigid static actor, but we don't have any shape defined for it. So, we will do this by calling the createShape() function and putting PxPlaneGeometry() as the first parameter, which defines the plane shape and a reference to the mMaterial that we created before as the second parameter. Finally, we add the actor by calling PxScene::addActor and putting the reference of plane, as shown in the following code: //1-Creating static plane PxTransform planePos = PxTransform(PxVec3(0.0f, 0, 0.0f),PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f))); PxRigidStatic* plane = gPhysicsSDK->createRigidStatic(planePos); plane->createShape(PxPlaneGeometry(), *mMaterial); gScene->addActor(*plane); The next actor we want to create is a dynamic actor having box geometry, situated 10 units above our static plane. A rigid dynamic actor can be created by calling the PxCreateDynamic() function, which requires five parameters of type: PxPhysics, PxTransform, PxGeometry, PxMaterial, and PxReal respectively. Because we want to place it 10 units above the origin, the first parameter of PxTransform will be PxVec3(0.0f,10.0f,0.0f). Notice that they component of the vector is 10, which will place it 10 units above the origin. Also, we want it at its default identity rotation, so we skipped the second parameter of the PxTransform class. An instance of PxBoxGeometry also needs to be created, which requires PxVec3 as a parameter, which describes the dimension of a cube in half extent. We finally add the created actor to the PhysX scene by calling PxScene::addActor() and providing the reference of gBox as the function parameter. PxRigidDynamic*gBox); //2) Create cube PxTransform boxPos(PxVec3(0.0f, 10.0f, 0.0f)); PxBoxGeometry boxGeometry(PxVec3(0.5f,0.5f,0.5f)); gBox = PxCreateDynamic(*gPhysicsSDK, boxPos, boxGeometry, *mMaterial, 1.0f); gScene->addActor(*gBox); Simulating PhysX Simulating a PhysX program requires calculating the new position of all of the PhysX actors that are under the effect of Newton's law, for the next time frame. Simulating a PhysX program requires a time value, also known as time step, which forwards the time in the PhysX world. We use the PxScene::simulate() method to advance the time in the PhysX world. Its simplest form requires one parameter of type PxReal, which represents the time in seconds, and this should always be more than 0, of else the resulting behavior will be undefined. After this, you need to call PxScene::fetchResults(), which will allow the simulation to finish and return the result. The method requires an optional Boolean parameter, and setting this to true indicates that the simulation should wait until it is completed, so that on return the results are guaranteed to be available. //Stepping PhysX PxReal myTimestep = 1.0f/60.0f; void StepPhysX() { gScene->simulate(myTimestep); gScene->fetchResults(true); } We will simulate our PhysX program in a loop until the dynamic actor (box) we created 10 units above the ground falls to the ground and comes to an idle state. The position of the box is printed on the console for each time step of the PhysX simulation. By observing the console, you can see that initially the position of the box is (0, 10, 0), but the y component, which represents the vertical position of the box, is decreasing under the effect of gravity during the simulation. At the end of loop, it can also be observed that the position of the box in each simulation loop is the same; this means the box has hit the ground and is now in an idle state. //Simulate PhysX 300 times for(int i=0; i<=300; i++) { //Step PhysX simulation if(gScene) StepPhysX(); //Get current position of actor (box) and print it PxVec3 boxPos = gBox->getGlobalPose().p; cout<<"Box current Position ("<<boxPos.x <<" "<<boxPos.y <<" "<<boxPos.z<<")n"; } Shutting down PhysX Now that our PhysX simulation is done, we need to destroy the PhysX related objects and release the memory. Calling the PxScene::release() method will remove all actors, particle systems, and constraint shaders from the scene. Calling PxPhysics::release() will shut down the entire physics. Soon after, you may want to call PxFoundation::release() to release the foundation object, as follows: void ShutdownPhysX() { gScene->release(); gPhysicsSDK->release(); gFoundation->release(); } Summary We finally created our first PhysX program and learned its steps from start to finish. To keep our first PhysX program short and simple, we just used a console to display the actor's position during simulation, which is not very exciting; but it was the simplest way to start with PhysX. Resources for Article: Further resources on this subject: Building Events [Article] AJAX Form Validation: Part 1 [Article] Working with Zend Framework 2.0 [Article]
Read more
  • 0
  • 0
  • 2577
Modal Close icon
Modal Close icon