You can read and reply to posts and download all mods without registering.
We're an independent and non-profit fan-site. Find out more about us here.
// A squirrel.osm port of the C++ SS2 overlay sample ("ss2_overlay_sample.cpp")// This can be used in place of "ss2sample.osm" with the "Demo_OverlaySampleOsm.mis" mission.// Adapted by RoSoDude using T2_overlay_sample.nut//// Local helper classes for individual HUD elements etc.////class sRect{ left = 0; top = 0; right = 0; bottom = 0; function IsPtInside(x, y) { return x >= left && y >= top && x < right && y < bottom; }}// ---------------------------------------------------------------// base class for our HUD elementsclass cHudElement{ m_bActive = false; m_rect = null; constructor() { m_rect = sRect(); } function Toggle() { m_bActive = !m_bActive; } function Show() { m_bActive = true; OnShow(TRUE); } function Hide() { m_bActive = false; OnShow(FALSE); } // required functions in derived classes function CalcPlacement() {} function OnShow(bShow) {} function MouseClick(x, y) { return false; } function MouseDblClick(x, y) { return false; } function MouseDragDrop(x, y, start_drag, cursor_mode) { return false; } function OnKey(ch, keycode) { return false; } function Draw() {}}// a custom HUD elementclass cHudElement_Something extends cHudElement{ m_bgImage = 0; // keep two temp int_ref objects around which are useful when calling service functions that have integer reference parameters // (avoids constant object creation and deletion if these were created as temp local vars) iref1 = int_ref(); iref2 = int_ref(); constructor() { base.constructor(); m_bgImage = ShockOverlay.GetBitmap("cyber", "iface\\"); CalcPlacement(); } function CalcPlacement() { m_rect.left = 0; m_rect.top = 0; ShockOverlay.GetBitmapSize(m_bgImage, iref1, iref2); m_rect.right = iref1.tointeger(); m_rect.bottom = iref2.tointeger(); m_rect.right += m_rect.left; m_rect.bottom += m_rect.top; } function Draw() { ShockOverlay.DrawBitmap(m_bgImage, m_rect.left, m_rect.top); }}// another custom HUD elementclass cHudElement_SomethingElse extends cHudElement{ m_bgImage = 0; // keep two temp int_ref objects around which are useful when calling service functions that have integer reference parameters // (avoids constant object creation and deletion if these were created as temp local vars) iref1 = int_ref(); iref2 = int_ref(); constructor() { base.constructor(); m_bgImage = ShockOverlay.GetBitmap("ammodiag", "iface\\"); CalcPlacement(); } function CalcPlacement() { Engine.GetCanvasSize(iref1, iref2); local w = iref1.tointeger(); local h = iref2.tointeger(); ShockOverlay.GetBitmapSize(m_bgImage, iref1, iref2); local bm_w = iref1.tointeger(); local bm_h = iref2.tointeger(); m_rect.left = w-bm_w; m_rect.top = 0; m_rect.right = m_rect.left + bm_w; m_rect.bottom = m_rect.top + bm_h; } function Draw() { ShockOverlay.DrawBitmap(m_bgImage, m_rect.left, m_rect.top); ShockOverlay.DrawString("Click me", m_rect.left+20, m_rect.top+12); } function MouseClick(x, y) { // do something ShockOverlay.ToggleLookCursor(); return true; }}// takes numeric keyboard input and draws string// RSD: Many edits here to fix discrepancies between C++ and Squirrel regarding chars, ints, strings, and arraysclass cHudElement_NumInput extends cHudElement{ static MAX_TEXT = 8; m_text = array(10); //RSD: MAX_TEXT+2, Squirrel throws error if index MAX_TEXT is used here m_cursorpos = 0; textdisp = ""; //RSD: Needed for string input later // keep two temp int_ref objects around which are useful when calling service functions that have integer reference parameters // (avoids constant object creation and deletion if these were created as temp local vars) iref1 = int_ref(); iref2 = int_ref(); /*constructor() { base.constructor(); }*/ constructor() { base.constructor(); m_text[0] = (0).tochar(); //RSD: Handle char conversion manually m_cursorpos = 0; //ShockOverlay.SetCustomFont(0, "bignum", "fonts\\"); CalcPlacement(); } function CalcPlacement() { // stick it somewhere in the middle Engine.GetCanvasSize(iref1, iref2); local w = iref1.tointeger(); local h = iref2.tointeger(); m_rect.left = w/2; m_rect.top = h/2 + 40; m_rect.right = m_rect.left + 100; m_rect.bottom = m_rect.top + 20; } function OnShow(bShow) { m_text[0] = (0).tochar(); //RSD: Handle char conversion manually m_cursorpos = 0; // make sure keypad HUD isn't active ShockGame.OverlayChange(kOverlayKeypad, kOverlayModeOff); ShockOverlay.SetKeyboardInputCapture(bShow); } function Draw() { // draw a blinking underscore at cursor pos if ((ShockGame.SimTime()/500) & 1) { m_text[m_cursorpos] = "_"; m_text[m_cursorpos+1] = (0).tochar(); //RSD: Handle char conversion manually } ShockOverlay.SetTextColor(255, 255, 0); //ShockOverlay.SetFont(2); ShockOverlay.SetFont(1); textdisp = m_text.reduce(function(p,c) { if (c != null) return p.tostring() + c.tostring(); else return p.tostring(); }); //RSD: Squirrel reads array pointer if used directly as input string ShockOverlay.DrawString(textdisp, m_rect.left, m_rect.top); ShockOverlay.SetFont(0); ShockOverlay.SetTextColor(-1, 0, 0); m_text[m_cursorpos] = (0).tochar(); //RSD: Handle char conversion manually } function OnKey(ch, keycode) { // process number key from main keyboard and numberic key pad both when numlock is on and off switch(keycode) //RSD: Squirrel can't work with chars as ints (nor will it compare strings bitwise with ints) { case ('0').tointeger(): case ('0').tointeger()|KB_FLAG_2ND: case KEY_PAD_INS: ProcessKey(0); break; case ('1').tointeger(): case ('1').tointeger()|KB_FLAG_2ND: case KEY_PAD_END: ProcessKey(1); break; case ('2').tointeger(): case ('2').tointeger()|KB_FLAG_2ND: case KEY_PAD_DOWN: ProcessKey(2); break; case ('3').tointeger(): case ('3').tointeger()|KB_FLAG_2ND: case KEY_PAD_PGDN: ProcessKey(3); break; case ('4').tointeger(): case ('4').tointeger()|KB_FLAG_2ND: case KEY_PAD_LEFT: ProcessKey(4); break; case ('5').tointeger(): case ('5').tointeger()|KB_FLAG_2ND: case KEY_PAD_CENTER: ProcessKey(5); break; case ('6').tointeger(): case ('6').tointeger()|KB_FLAG_2ND: case KEY_PAD_RIGHT: ProcessKey(6); break; case ('7').tointeger(): case ('7').tointeger()|KB_FLAG_2ND: case KEY_PAD_HOME: ProcessKey(7); break; case ('8').tointeger(): case ('8').tointeger()|KB_FLAG_2ND: case KEY_PAD_UP: ProcessKey(8); break; case ('9').tointeger(): case ('9').tointeger()|KB_FLAG_2ND: case KEY_PAD_PGUP: ProcessKey(9); break; case KEY_BS: case KEY_DEL: case KEY_PAD_DEL: ProcessKey(-1); break; case KEY_ENTER: case KEY_GREY_ENTER: // dactivate HUD element on return/enter Hide(); break; default: // unhandled key return false; } return true; } function ProcessKey(num) { if (num == -1) { // delete if (m_cursorpos > 0) { m_cursorpos--; m_text[m_cursorpos] = (0).tochar(); //RSD: Handle char conversion manually } return; } if (m_cursorpos < MAX_TEXT) { m_text[m_cursorpos] = (('0').tointeger() + num).tochar(); //RSD: Handle char conversion manually m_cursorpos++; m_text[m_cursorpos] = (0).tochar(); //RSD: Handle char conversion manually } }};// ---------------------------------------------------------------// base class for our transparent (non-interactive) overlay elementsclass cOverlayElement{ m_bActive = false; m_handle = -1; constructor() { } function Toggle() { m_bActive = !m_bActive; } function Show() { m_bActive = true; } function Hide() { m_bActive = false; } // required functions in derived classes function CalcPlacement() {} function Draw() {}}// a custom overlay elementclass cOverlayElement_Something extends cOverlayElement{ // keep four temp int_ref objects around which are useful when calling service functions that have integer reference parameters // (avoids constant object creation and deletion if these were created as temp local vars) iref1 = int_ref(); iref2 = int_ref(); iref3 = int_ref(); iref4 = int_ref(); constructor() { base.constructor(); // create a simple static overlay of a bitmap CalcPos(iref1,iref2); local x = iref1.tointeger(); local y = iref2.tointeger(); local bm = ShockOverlay.GetBitmap("hackicon", "iface\\"); m_handle = ShockOverlay.CreateTOverlayItemFromBitmap(x, y, 127, bm, false); } function CalcPos(xref, yref) { // place it where the alarm icon would normal be shown ShockOverlay.GetOverlayRect(kOverlayAlarm, xref, yref, iref3, iref4); } function CalcPlacement() { CalcPos(iref1,iref2); local x = iref1.tointeger(); local y = iref2.tointeger(); ShockOverlay.UpdateTOverlayPosition(m_handle, x, y); } function Draw() { ShockOverlay.DrawTOverlayItem(m_handle); }}// another custom overlay elementclass cOverlayElement_SomethingElse extends cOverlayElement{ m_bUpdateContents = false; m_bgImage = 0; x = 0; y = 0; // keep four temp int_ref objects around which are useful when calling service functions that have integer reference parameters // (avoids constant object creation and deletion if these were created as temp local vars) iref1 = int_ref(); iref2 = int_ref(); iref3 = int_ref(); iref4 = int_ref(); constructor() { base.constructor(); // create a dynamic/comlpex overlay with 64x64 size CalcPos(); m_handle = ShockOverlay.CreateTOverlayItem(x, y, 64, 64, 127, false); m_bUpdateContents = true; // get our bg bitmap m_bgImage = ShockOverlay.GetBitmap("alarm", "iface\\"); } function CalcPos() { // place it right of where the alarm icon would normal be shown ShockOverlay.GetOverlayRect(kOverlayAlarm, iref1, iref2, iref3, iref4); x = iref1.tointeger(); y = iref2.tointeger(); local w = iref3.tointeger(); x += w + 4; // xref = x.int_ref(); } function CalcPlacement() { CalcPos(); ShockOverlay.UpdateTOverlayPosition(m_handle, x, y); } function Draw() { // draw overlay contents to update it if something changed if (m_bUpdateContents) { m_bUpdateContents = false; if ( ShockOverlay.BeginTOverlayUpdate(m_handle) ) { local s = ShockGame.GetPlayerPsiPoints(); ShockOverlay.GetStringSize(s, iref1, iref2); local w = iref1.tointeger(); local h = iref2.tointeger(); ShockOverlay.DrawBitmap(m_bgImage, 0, 0); ShockOverlay.DrawString(s, 64-w-4, 64-16); ShockOverlay.EndTOverlayUpdate(); } } ShockOverlay.DrawTOverlayItem(m_handle); }}/****************************************************************************///// The overlay handler interface// Receives calls from the engine. Only one handler (per OSM) can be active at a time.//class cMyShockOverlay extends IShockOverlayHandler{ m_elems = []; m_overlays = []; /*constructor() { base.constructor(); }*/ function FindElementFromPt(x, y) { foreach (o in m_elems) if (o.m_bActive && o.m_rect.IsPtInside(x,y)) return o; return null; } function Init() { m_elems = []; m_elems.append( cHudElement_Something() ); m_elems.append( cHudElement_SomethingElse() ); m_elems.append( cHudElement_NumInput() ); m_overlays = []; m_overlays.append( cOverlayElement_Something() ); m_overlays.append( cOverlayElement_SomethingElse() ); // show em all foreach (o in m_elems) o.Show(); foreach (o in m_overlays) o.Show(); } function Term() { foreach (i, o in m_elems) m_elems[i] = null; foreach (i, o in m_overlays) m_overlays[i] = null; } // // IShockOverlayHandler interface // function DrawHUD() { foreach (o in m_elems) if (o.m_bActive) o.Draw(); } function DrawTOverlay() { foreach (o in m_overlays) if (o.m_bActive) o.Draw(); } function OnUIEnterMode() { foreach (o in m_elems) o.CalcPlacement(); foreach (o in m_overlays) o.CalcPlacement(); } function CanEnableElement(which) { // prevent the alarm icon from being displayed if (which == kOverlayAlarm) return false; // deactivate numeric input HUD elem if keypad is about to be shown else if (which == kOverlayKeypad) m_elems[2].Hide(); return true; } function IsMouseOver(x, y) { // see if mouse cursor is inside any of our custom elements return FindElementFromPt(x, y) != null; } function MouseClick(x, y) { local pElem = FindElementFromPt(x, y); if (pElem) return pElem.MouseClick(x, y); return false; } function MouseDblClick(x, y) { local pElem = FindElementFromPt(x, y); if (pElem) return pElem.MouseDblClick(x, y); return false; } function MouseDragDrop(x, y, start_drag, cursor_mode) { local pElem = FindElementFromPt(x, y); if (pElem) return pElem.MouseDragDrop(x, y, start_drag, cursor_mode); return false; } function HandleKey(ch, keycode) { if (keycode & KB_FLAG_DOWN) { foreach (o in m_elems) if ( o.OnKey(ch, keycode&~KB_FLAG_DOWN) ) return true; } return false; }}// create a global instance of the overlay handlermyOverlay <- cMyShockOverlay();// ================================================================================// Script that installs and uninstalls the overlay handlerclass MyHudScript extends SqRootScript{ function destructor() { // to be on the safe side make really sure the handler is removed when this script is destroyed // (calling RemoveHandler if it's already been removed is no problem) ShockOverlay.RemoveHandler(myOverlay); } function OnBeginScript() { ShockOverlay.AddHandler(myOverlay); myOverlay.Init(); } function OnEndScript() { ShockOverlay.RemoveHandler(myOverlay); myOverlay.Term(); }}
The DrawHUD() and DrawTOverlay() overlay handler functions run continuously...