Capricorn 76
The runDemo.e76script script runs all the demos. It's the startup-script that initialises the engine, loads a 3D world and runs the main processing loop. Feel free to use it as a starting point for your own applications.

The runDemo.e76script:

---------------------------
---------------------------
-- Run a ScriptENGINE Demo.
-- This script performs the necessary steps to load and run a 3D world in the ScriptENGINE.
--
-- Copyright (c) 2008-09 Capricorn 76 Pty. Ltd.
--
-- When run from the command-prompt, this script will:
-- Enter the runDemo state,
-- Initialise the graphics/physics/sound engines,
-- Display a list of the demos, waiting for the user to select one,
-- Runs the engine, waiting for the ESCAPE key to be pressed,
-- Exits the state.
---------------------------
---------------------------

-----------------
-- PRIVATE FUNCTION
-- Some demos require the ScriptENGINE to be registered.
-- To register the ScriptENGINE, call IApp:registerDeveloper().
-- This script will ask for the license details once, and then store them in an options file.
-----------------
local function _checkLicense()
    local developerEmail        = IApp:getOption('Demo', 'LicenseEmail');
    local licenseKey            = IApp:getOption('Demo', 'LicenseKey');

    -- Attempt to perform registration. If it fails, the function returns nil.
    local registered            =IApp:registerDeveloper(developerEmail, licenseKey);

    -- Is the regstration valid?
    if (not(registered)) then
        print('--------------------------');
        print('Registering your ScriptENGINE License');
        print('--------------------------');
        io.write('Enter your developer email address:');
        developerEmail          = io.read();
        io.write('Enter your license key:');
        licenseKey              = io.read();

        -- Attempt to re-register
        registered          =IApp:registerDeveloper(developerEmail, licenseKey);

        -- If registration successful, then update the program options.
        -- This script will save program options on cleanup.
        IApp:setOption('Demo', 'LicenseKey', licenseKey);
        IApp:setOption('Demo', 'LicenseEmail', developerEmail);
    end

    if (registered) then
        print('ScriptENGINE Registration: SUCCESS');
    else
        print('ScriptENGINE Registration: FAILED');
    end

    return registered;
end


-----------------
-- PRIVATE FUNCTION
-- Display available demos to use and get their selection
-----------------
local function _getSelection()
    print('-------------------------------------');
    print('-- ScriptENGINE Demos');
    print('-------------------------------------');

    -- Ask the ScriptENGINE for a list of sub-folders in the main program's folder starting with a '['
    local folders = IApp:getFilenameListFromFileSystem('[*.', true, './');
    if (folders) then

        -- Now we will have a list of our demo folders.
        -- Display these in the console
        for i = 1, table.getn(folders) do
            print(tostring(i) .. ') ', tostring(folders[i]));
        end

    end

    print('-------------------------------------');
    print('Please select a demo (by entering its number):');
    io.input();
    local selection = io.read('*n');

    -- If input is valid, then return it
    if (selection and (selection >= 1) and (selection <= table.getn(folders))) then
        return folders[selection];
    end
end

-----------------
-- PRIVATE FUNCTION
-- Initialise the graphics/physics/sound engines.
-----------------
local function _engineInitialise()
    -----------------
    -- Load constants files we will use from the ScriptENGINE distribution
    -----------------
    IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsVideoDrivers.e76script');        -- Graphics driver constants
    IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsGuiSkinParams.e76script');   -- Constants used with the ISkin interface
    IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsSoundDrivers.e76script');        -- Sound driver constants

    -----------------
    -- Add search paths to managed filesystem
    -----------------
    IApp:addSearchPath('./Resources');

    -----------------
    -- Display demos to user and get their selection
    -----------------
    local demoFolder = _getSelection();

    if (not(demoFolder)) then
        return; -- No demo selected
    end

    -----------------
    -- Graphics engine
    -----------------
    print('Please select graphics driver:');
    print('1) DirectX');
    print('2) Open GL');
    print('3) Software');
    local option = io.read('*n');

    local graphicsDriver = GRAPHICS_DIRECTX;    -- Set default to DirectX
    if  (option == 2) then
        graphicsDriver = GRAPHICS_OPENGL;
    elseif  (option == 3) then
        graphicsDriver = GRAPHICS_SOFTWARE;
    end

    local graphicsOk = IGraphics:init(  graphicsDriver,
                            800,
                            600,
                            false,
                            32,
                            false,
                            false,
                            false,
                            50,
                            true);

    -- If we fail to initialise the graphics engine,
    -- we will try a fallback option
    if (not(graphicsOk)) then

        local errorMsg =    'Graphics engine failed to initialise... the default settings are not compatible with your graphics card.\n' ..
                    'Trying fallback options using a software renderer...\n' ..
                    'NB: Some demos may not display properly using the software renderer.\n' ..
                    'Press any key to continue...';

        IApp:showMessageBoxOk(errorMsg, 'Graphics Error');

        IGraphics:init(         GRAPHICS_SOFTWARE,
                            800,
                            600,
                            false,
                            16,
                            false,
                            false,
                            false,
                            30,
                            false); -- this time we want an error to be displayed
    end

    print('ScriptENGINE Graphics Driver:', IGraphics:getCurrentDriverName());
    print('ScriptENGINE Demos © Capricorn 76 2007-09');

    -----------------
    -- Physics engine
    -----------------
    IPhysics:init(          1,
                        1,
                        0.6,
                        0.5,
                        0,
                        0,
                        1000,
                        true,
                        50,
                        false); -- If an error occurs, we want it displayed. It must be intialised...

    -----------------
    -- Sound engine
    -----------------
    local soundOk = ISound:init(    'AUTO_DETECT_SOUND',
                        20,
                        0,
                        true);

    if (soundOk) then
        print('ScriptENGINE Sound Driver:', ISound:getCurrentDriverName());
        ISound:setDistanceModel(SOUND_DISTANCE_INVERSE_CLAMPED);

        -- Some of the demos set their sfx volumes by reading the program's options
        IApp:setOptionInt('soundSettings', 'volume', 1);
    else
        local errorMsg =    'Sound engine failed to initialise... cannot find sound card support.\n' ..
                    'NB: Some demos using sound effects will not operate.\n' ..
                    'Press any key to continue...';

        IApp:showMessageBoxOk(errorMsg, 'Sound Error');
    end

    -- Load a GUI skin
    ISkin:activate('demo');

    -- Return the selected demo folder
    return demoFolder;
end

-----------------
-- PRIVATE FUNCTION
-- Cleanup the graphics/physics/sound engines.
-----------------
local function _engineCleanup()
    ISound:destroy();
    IPhysics:destroy();
    IGraphics:destroy();
end

---------------------------
-- SCRIPTENGINE STATE ENTRY POINT.
---------------------------
-- This is the 1st state executed by the ScriptENGINE state manager, when the script is run from the command-prompt, or double-clicked from Windows Explorer.
--  The startup state name is derived from the startup script's name (it's the filename without the extension)
--
-- States can also be queued using the IState interface.
--  See the doco on the IState interface for more info about the ScriptENGINE state manager.
---------------------------
---------------------------
function OnStateRun_runDemo(param)
    ----------------------
    -- Check ScriptENGINE version
    ----------------------
    if (not(IApp:testAppVersion(3, 0))) then
        IApp:showMessageBoxOk('ScriptENGINE version 3.0 (or greater) required.\nPlease download the latest fom www.capricorn76.com', 'ScriptENGINE') ;
        return;
    end

    -----------------
    -- Load options file.
    -- We use it to store the user's license info.
    -----------------
    if (IApp:fileExists('options.e76cfg')) then
        IApp:loadOptions('options.e76cfg');
    end

    -----------------
    -- Turn on console, so we can communicate with user
    -----------------
    IApp:showConsoleWindow();

    -----------------
    -- Attempt to register a ScriptENGINE license.
    --  NB: licenses are only available with a copy of the SDK.
    -----------------
    _checkLicense();

    -----------------
    -- Constants used in this demo can be loaded from the ScriptENGINE distribution folders
    -----------------
    IApp:loadScript(IApp:getExeFilePath() .. './Constants/constantsGuiAlignments');

    -----------------
    -- Initialise the graphics/physics/sound engines.
    -- Also gets the user's selection that determines what demo is run.
    -----------------
    local demoPath = _engineInitialise();

    -- If no demo selected, then exit immediately.
    if (not(demoPath)) then
        return;
    end

    -----------------
    -- Set the default mouse position to the middle of the screen
    -----------------
    IMouse:setType('WAIT');

    -----------------
    -- Subscribe to gui events, to process the menu selections.
    -- ScriptENGINE will call the subscriber callback on a GUI event.
    -----------------
    local subGui = IEvents:subscribeGui('__OnGui');

    -----------------
    -- Show loading text
    -----------------
    IGraphics:createText('loadingText', 'Loading... Please wait...', '0.2 0.45 0.8 0.55', true, false, false, '1 1 1 1');
    IGraphics:setStaticTextAlignment('loadingText', GUI_JUSTIFY_CENTER, GUI_JUSTIFY_CENTER);
    IGraphics:draw();   -- Draw a single frame, so the text will be displayed

    -----------------
    -- Load the GUI in preparation for the demos.
    -- Some demos, eg GUI demo, will load their own GUIs.
    -----------------
    IGraphics:loadGui('runDemo');


    -----------------
    -- Turn off auto-managing of active camera based upon camera type (eg. fps/pivot/satellite/etc cameras can auto-respond to mouse/key input)
    -- If the specific demo wants it on, they can turn it on...
    -- Or they can manually move the camera around according to their own rules.
    -----------------
    IWorld:setActiveCameraAutoProcessed(false);


    -----------------
    -- This global parameter can be manipulated by the demos to affect how the graphics loop is run.
    -- If an demo uses a skybox, then the back buffer will not be seen, and can be disabled to increase performance.
    -- NB: Global variables are defined without the 'local' keyword, and are available to all scripts loaded into the engine.
    -----------------
    graphicsBackBufferOff = false;

    -----------------
    -- Normally, the world script is loaded during the IWorld:load() function, together with the world data.
    -- But in these demos, we want to pre-load the world script, to allow any extra initialisation.
    -----------------
    if (IApp:loadScript(demoPath .. '/world')) then
        -- At this point, only the world script has been loaded into the engine. Not the 3D world data.
        -- After loading the script, we attempt to call OnWorldPreload() function in the world.e76script.
        -- Using the IApp:callScript() function gracefully handles when the function is not defined.
        -- We could simply call OnWorldPreload(demoPath), but this would raise an error if the function was not defined.
        IApp:callScript('OnWorldPreload', demoPath);
    end

    -----------------
    -- Load the demo's world.
    -- ScriptENGINE can also load the world.e76script (if found).
    -----------------
    if (IWorld:load(demoPath, 'worldData')) then
        -----------------
        -- Load shared guis. Visible on all demos.
        -----------------
        IGraphics:removeControl('loadingText');

        -----------------
        -- Call the demo's OnWorldLoad() function in the world.e76script
        -- This gives the demo a chance to perform initialisation after the world data is loaded.
        -- Using the IApp:callScript() function gracefully handles when the function is not defined.
        -----------------
        IApp:callScript('OnWorldLoad', demoPath);

        -----------------
        -- Run the engine processing loop.
        -- It will continue processing until the IApp:stop() is called (usually from an event subscriber callback).
        -- The IApp:run() can be run for a specific time by passing in the time limit to the function.
        -- Alternatively, you can create your own processing loop and call IApp:tick() instead of using IApp:run().
        -----------------
        IMouse:setType('ARROW');
        IApp:run(0, graphicsBackBufferOff);

        -----------------
        -- Call the demo's OnWorldUnload() function in the world.e76script
        -- This gives the demo a chance to perform specific cleanup.
        -- NB: Using the IApp:callScript() function allows us to gracefully handle the case when the function is not defined.
        -- We could simply call OnWorldUnload(demoPath), but this would raise an error if the function is not defined.
        -----------------
        IApp:callScript('OnWorldUnload', demoPath);

        -----------------
        -- Unload the 3D world
        -----------------
        IWorld:unload();
    end

    -----------------
    -- Remove the script functions from the engine. They can no longer be called.
    -----------------
    OnWorldPreload = nil;
    OnWorldLoad = nil;
    OnWorldUnload = nil;

    -----------------
    -- Restore mouse
    -----------------
    IMouse:setType('ARROW');

    -----------------
    -- Cleanup gui
    -----------------
    IGraphics:removeGui();

    -----------------
    -- Unsubscribe to events
    -----------------
    IEvents:unsubscribe(subGui);

    -----------------
    -- The graphics/physics/sound engines will be cleaned up.
    -----------------
    _engineCleanup();

    -----------------
    -- Save options file if the user is registered.
    -- We use it to store the user's license info.
    -----------------
    if (IApp:isRegistered()) then
        IApp:saveOptions('options.e76cfg');
    end
end

-----------------
-- Gui subscriber: Handle gui events by performing different action based upon the GUI control & event-type.
-- There are 2 main ways to test the GUI event data.
-- a) Compare the callerId to your GUI control identifiers, and compare the eventType to the GUI event types defined in ./Constants/constantsGuiEventTypes.e76script
-- b) Use the IGraphics utility functions like IGraphics:buttonClicked(), IGraphics:menuClicked() etc
-----------------
function __OnGui(callerId, eventType, userData)
    -----------------
    -- Exit menu
    -----------------
    if  (IGraphics:menuClicked('menuFileExit', callerId, eventType)) then
        -- Stop the IApp:run() processing loop and exist the state
        IApp:stop();

    -----------------
    -- View demo script menu
    -----------------
    elseif  (IGraphics:menuClicked('menuFileViewScript', callerId, eventType)) then
        local worldScriptLocation = IApp:pathClean(IWorld:getPathLong() .. '/world.e76script', '\\'); -- Windows needs \ path separators for shellExecute

        print('Opening:', worldScriptLocation, IWorld:getPathLong());
        if (not(IApp:shellExecute('edit', worldScriptLocation))) then
            IApp:showMessageBoxOk(  'Purchase the ScriptENGINE SDK from Capricorn 76.\n' ..
                                'It includes a code editor pre-installed with all the ScriptENGINE Interfaces and Functions',
                                'No Editor Installed');
        end

    -----------------
    -- View runDemo.e76script framework
    -----------------
    elseif (IGraphics:menuClicked('menuFileViewRunDemoScript', callerId, eventType)) then
        local scriptLocation = '.\\runDemo.e76script';

        print('Opening:', scriptLocation, IApp:getBasePath());
        if (not(IApp:shellExecute('edit', scriptLocation))) then
            IApp:showMessageBoxOk(  'Purchase the ScriptENGINE SDK from Capricorn 76.\n' ..
                                'It includes a code editor pre-installed with all the ScriptENGINE Interfaces and Functions',
                                'No Editor Installed');
        end
    end
end

Copyright © 2006-23 Sep 2009 Capricorn 76 Pty. Ltd. (created on Wed Sep 23 16:49:12 2009)