--------------------------- --------------------------- -- 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)