Introduction to ShiVa Editor Job – ShiVa Engine

Introduction to ShiVa Editor Job

A ShiVa Editor Job, unlike a normal function, is an editor background process. Jobs can be used for a large number of predefined tasks, such as asset import, game authoring, building of runtime assets, or source control. Unlike normal functions, jobs can be executed asynchronously which will prevent them from blocking the caller and the editor from freezing during long tasks.

Creating a Job

Before you can define what the job is supposed to do, you must first run job.create(). This will return a handle, which we will use from here on to refer to the job, define its behaviour, etc.

local hJob = job.create ( "" )
if ( hJob ) then
	-- your work here

job.create() has an optional parameter, which you can use to give your job a unique name. If you call a named job twice, the older job will be aborted and replaced by the new one. On the other hand, if you call a nameless job twice, you will create a second job that either waits for the first one to complete (synchronous behaviour), or computes in parallel (asynchronous behaviour). Naming a job vs. leaving it nameless should depend on whether you want to run multiple instances of the same job with different input (e.g. multi file imports, batch processing, etc.), or whether it is a long singular process that you may need to abort and replace. We will have a look at synchronous vs asynchronous jobs later.
All jobs in ShiVa need to declare their type through job.setType.

job.setType ( hImportJob, job.kTypeImportMovie )

You can pick the job type from a large number of predefined constants. There are jobs available for game authoring (job.kTypeAuthoringForAndroid, job.kTypeAuthoringForBlackBerry, job.kTypeAuthoringForFlash etc.), asset import (job.kTypeImportModel, job.kTypeImportMusic, job.kTypeImportEditionPackage etc.), building runtime assets (job.kTypeBuildRuntimeScript, job.kTypeBuildRuntimeSound, job.kTypeBuildRuntimeTexture etc.), and much more. Please check the job.* type constants for more information.

Job Properties

Once you have determined the type of job you want to run, you need to further define its behaviour through job properties. This again is largely accomplished through predefined constants.

job.setType ( hImportJob, job.kTypeImportSound )
job.setProperty ( hImportJob, job.kPropertyCompleteCallback, onProjectFileDialogJobHasCompleted )
job.setProperty ( hImportJob, job.kPropertyLogOutput, false )
job.setProperty ( hImportJob, job.kPropertySourceFile, string.trim ( aFileToImportPath [ iJob ], " " ) )
job.setProperty ( hImportJob, job.kPropertyDestinationName, sSoundFileName )
job.setProperty ( hImportJob, job.kPropertyDestinationDirectory, sProjectRootPath )
job.setProperty ( hImportJob, job.kPropertyDestinationTarget, hTarget )
job.setProperty ( hImportJob, job.kPropertyDescription, "Sound Import" )

In the example above, we only use properties that can be defined through strings, numbers and booleans. However there are different properties which require multiple imputs, such as vectors. In cases like these, the data has to be packed into tables:

local vTranslation = table.pack ( 1, 2, 1 )
job.setProperty ( hImportJob, job.kPropertyImportGlobalTranslation, vTranslation )

There are even instances of lists with nested tables. In the example below, we are importing everything from a DAE file except for dummies and cameras:

job.setProperty ( hImportJob, job.kPropertyImportProcessItemList, { true, { job.kImportItemDummy, false }, { job.kImportItemCamera, false } } )

Which constants require simple types and which ones require tables is either self explanatory (“..Name”, “..Description”), written down in the documentation (job.kPropertyImportProcessItemList), or can be easily deduced from the code in the Module sources.

Running a Job

When you have created and defined your job, it is time to run it. The 2nd parameter of the run() function allows you to switch between synchronous and asynchronous execution.

job.run ( hJob, true )

In synchronous mode, the function will return when the job is finished, and then continue executing the calling function. In most cases however, you want to run the job in asynchronous mode, so the job does not block the calling function. In this mode, run() will return as soon as the job has been launched.
You can launch as many asynchronous jobs as you need, but ShiVa can only execute up to 4 asynchronous jobs at a time. The remaining jobs will automatically be put in a queue and execute as soon as one of the 4 execution places is available. Keep in mind that only unnamed jobs will spawn new processes, while named jobs will replace their identically named predecessors.

Job control

Once a job is launched, the only control you have is the decision whether to run the job to completion or cancel it prematurely using job.cancel(). There are however a number of status checks you can do, and a number of maintenance tasks you have to perform.

Get Status

You can check on the status of a job by using various .is* functions, like isRunning, isCompleted, isFinalized etc.

function ParseCompileOutput ( hJob )
    if ( not job.isCanceled ( hJob ) ) then
        local sOutputError = job.getErrorOutput ( hJob )
        -- etc.

Finalizing

As mentioned previously, only a limited number of jobs can be executed at the same time. Once a job has finished, you are responsible for freeing the used resources. To get the result of the job, you have to query it separately before finalizing the job.

bJobSucess = job.getProperty ( hCurrentJob, job.kPropertyExecutionResult )
bJobSucess = job.finalize ( hCurrentJob ) and bJobSucess

Return Callback

To make it easy for your asynchronous jobs to notify you when they are done, you should always define a callback function.

job.setProperty ( hImportJob, job.kPropertyCompleteCallback, onProjectFileDialogJobHasCompleted )

The callback function takes the job handle as its only argument, which can be used to query the result of the job.

function onProjectFileDialogJobHasCompleted ( hJob )
    if ( hJob ) then
        if ( job.isCanceled ( hJob ) or ( job.getProperty ( hJob, job.kPropertyExecutionResult ) == false ) ) then
			-- canceled or failed
		else
			-- probably successful
			-- etc



Need more answers?

  • slackBanner