Capricorn 76
Threading example.
Threads are used to build concurrent programs.
You can create multiple threads that run at the same time,
and are independent of the main ScriptENGINE processing.
They are useful for long background tasks preventing
your processing from bogging down the ScriptENGINE.

---------------------------
---------------------------
-- Threading example
-- Copyright (c) 2007-09 Capricorn 76 Pty. Ltd.
--
-- Threads are used to build concurrent programs.
-- You can create multiple threads that run at the same time,
-- and are independent of the main ScriptENGINE processing.
-- They are useful for long background tasks preventing
-- your processing from bogging down the ScriptENGINE.
--
-- For example, if all your processing ran between graphics
-- engine frame updates, the frame rate would get jerky
-- as your processing loads increase.
--
-- Threads are especially powerful on computers with
-- multiple CPUs. The threads will utilise the CPUs
-- more effectively than a single threaded program.
--
-- NOTE:
-- The ./Demos/runDemo.e76script is a utility script used to run all the examples.
-- It loads the world, calls the OnWorldLoad(), OnWorldUnload() functions, and runs the graphics engine loop, waiting for the user to press escape.
---------------------------
---------------------------

-- Load required modules
require "lanes"

local subMouse;
local thread1Id, thread2Id, thread3Id;

---------------------------
-- The thread entry point.
-- The input parameter is used to pass in the cube identifier.
-- It's passed in when the thread is created.
---------------------------
local function OnThreadRun(cubeId, seed)
    math.randomseed(seed);

    while (true) do
        --print('OnThreadRun:', cubeId);

        -- Rotate the cube
        IWorld:manipulateEntity(cubeId, 'rotate', 0, 1, 1);

        -- Change its color
        local col = IMisc:colorCreate(math.random(), math.random(), math.random(), 0);
        IGraphics:setEntityEmissiveColor(cubeId, -1, col);

        -- Delay the thread
        IApp:sleep(100);
    end
end

---------------------------
-- runDemo.e76script calls this function when the world is loaded
---------------------------
function OnWorldLoad(worldName)
    --print('OnWorldLoad');

    ---------------------------
    -- The SDK world editor creates a worldIds.e76script when the world is saved. It contains all the entity ids.
    -- We load the IDs so that we can refer to the world entities using friendly names.
    ---------------------------
    IApp:loadScript(IWorld:getNameLong() .. '/worldIds');
    IWorld:setActiveCameraId(idCamera_cam1);

    ---------------------------
    -- Load example's GUI
    ---------------------------
    OnWorldLoadGui();

    ---------------------------
    -- Create periodic threads. The OnThreadRun() function in the script file
    -- will be called periodically by the ScriptENGINE.
    -- All the thread data is independent to the rest of the ScriptENGINE.
    --
    -- The OnThreadRun() can take an input parameter: we pass in the cube identifier.
    -- We could also specify a callback function name that will be called when the thread ends.
    ---------------------------
    local threadGenerator = lanes.gen("engine,math", {cancelstep=10}, OnThreadRun);
    thread1Id = threadGenerator(idUnit_box1, os.time());
    thread2Id = threadGenerator(idUnit_box2, os.time()+1);
    thread3Id = threadGenerator(idUnit_box3, os.time()+2);

    ---------------------------
    -- Subscribe to mouse click events.
    -- The graphics engine will notify us via our callback function
    -- whenever the user clicks a mouse button.
    ---------------------------
    subMouse = IEvents:subscribeMouseButton('OnMouseButton');
end

---------------------------
-- Load example's GUI
---------------------------
function OnWorldLoadGui()
    IGraphics:loadGui('help');
end

---------------------------
-- runDemo.e76script calls this function when the world is unloaded
---------------------------
function OnWorldUnload(worldName)
    --print('OnWorldUnload');

    ---------------------------
    -- Unsubscribe to events.
    -- We will no longer be notified.
    ---------------------------
    IEvents:unsubscribe(subMouse);

    -- Stop all threads
    thread1Id:cancel();
    thread2Id:cancel();
    thread3Id:cancel();
end

-----------------------------
-- Mouse button handler.
-- The graphics engine will call this function
-- whenever the user clicks a mouse button.
--
-- We can check what event type was fired and act accordingly.
-----------------------------
function OnMouseButton(eventType, mouseX, mouseY, mouseWheel, userData)

    ---------------------------
    -- Was the left-mouse button clicked?
    ---------------------------
    if (IMouse:leftButtonClicked(eventType)) then

        ---------------------------
        -- We do a ray cast using the graphics engine to mouse-select a cube.
        --
        -- We are only interested in units (that's why we are using the filter).
        -- To include more entity types in the filter, simply add their typeids.
        ---------------------------
        id = IGraphics:rayCastMousePositionFilter(IWorld:getUnitTypeId());

        print('Mouse button clicked:', id);

        if (id) then

            ---------------------------
            -- We will stop the thread corresponding to the selected cube
            ---------------------------
            if (id == idUnit_box1) then
                print('Cancel thread1Id');
                thread1Id:cancel();

            elseif (id == idUnit_box2) then
                print('Cancel thread2Id');
                thread2Id:cancel();

            elseif (id == idUnit_box3) then
                print('Cancel thread3Id');
                thread3Id:cancel();

            end
            return true; -- Indicates that we handled the event. Don't pass it on.
        end

    end

end

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