337 lines
9.5 KiB
Plaintext
Executable File
337 lines
9.5 KiB
Plaintext
Executable File
--
|
|
-- Notify Popup Box
|
|
-- briefly shows a warning-box in corner of Max window, with optional object-select or other-function button
|
|
--
|
|
-- Neal D Corbett
|
|
-- Rockstar Leeds
|
|
-- 09/08/2011
|
|
--
|
|
|
|
-- USAGE: https://devstar.rockstargames.com/wiki/index.php/Dev:Notifier_Popup
|
|
-- To create get a simple message popup: (text message, with "OK" button to dismiss)
|
|
-- RsNotifyPopUp_create text:"Text" title:"Title"
|
|
|
|
global RsNotifyPopUp, RsNotifyPopUp_closeTimer, RsNotifyPopUp_scrollTimer
|
|
global RsNotifyPopUp_func, RsNotifyPopUp_selFunc, RsNotifyPopUp_objs, RsNotifyPopUp_scrollIncrement
|
|
global RsNotifyPopUp_startPos, RsNotifyPopUp_targetYPos, RsNotifyPopUp_targetHeight, RsNotifyPopUp_returning
|
|
|
|
-- Clear away the popup form and timers:
|
|
fn RsNotifyPopUp_cleanup =
|
|
(
|
|
if (RsNotifyPopUp != undefined) do
|
|
(
|
|
dotNet.removeAllEventHandlers RsNotifyPopUp
|
|
RsNotifyPopUp.close()
|
|
RsNotifyPopUp = undefined
|
|
)
|
|
|
|
for globalName in #("RsNotifyPopUp_closeTimer", "RsNotifyPopUp_scrollTimer") do
|
|
(
|
|
local val = globalVars.get globalName
|
|
if (val != undefined) do
|
|
(
|
|
globalVars.set globalName undefined
|
|
val.dispose()
|
|
)
|
|
)
|
|
|
|
RsNotifyPopUp_objs = undefined
|
|
RsNotifyPopUp_func = undefined
|
|
RsNotifyPopUp_selFunc = undefined
|
|
)
|
|
|
|
-- Create notify popup-box:
|
|
fn RsNotifyPopUp_create text:"" title:"" func: selFunc: width:270 objs: scrollIncrement:2 scrollInterval:10 timeOut:4000 instantly:True =
|
|
(
|
|
RsNotifyPopUp_cleanup()
|
|
|
|
-- Set up global variables for selecting/running functions:
|
|
if (func != unsupplied) do
|
|
(
|
|
RsNotifyPopUp_func = func
|
|
)
|
|
if (objs != unsupplied) do
|
|
(
|
|
RsNotifyPopUp_objs = objs
|
|
)
|
|
if (selFunc != unsupplied) do
|
|
(
|
|
RsNotifyPopUp_selFunc = selFunc
|
|
)
|
|
|
|
-- Define timer-event to move the popup up/down and trigger its actions when it reaches its up/down positions:
|
|
fn scrollTimerEvent =
|
|
(
|
|
try
|
|
(
|
|
local currentPosY = RsNotifyPopUp.location.y
|
|
|
|
case of
|
|
(
|
|
(not RsNotifyPopUp_returning and (currentPosY > RsNotifyPopUp_targetYPos)):
|
|
(
|
|
-- Expand the form:
|
|
if (RsNotifyPopUp.height < RsNotifyPopUp_targetHeight) do
|
|
(
|
|
RsNotifyPopUp.height += RsNotifyPopUp_scrollIncrement
|
|
)
|
|
|
|
-- Move the form up:
|
|
RsNotifyPopUp.location.y -= RsNotifyPopUp_scrollIncrement
|
|
)
|
|
(RsNotifyPopUp_returning and (currentPosY < RsNotifyPopUp_startPos.y)):
|
|
(
|
|
if (RsNotifyPopUp.bounds.contains RsNotifyPopUp.mousePosition) then
|
|
(
|
|
-- Send the form back up if it's moused over:
|
|
dotNet.removeAllEventHandlers RsNotifyPopUp
|
|
RsNotifyPopUp_returning = false
|
|
)
|
|
else
|
|
(
|
|
-- Shrink the form:
|
|
if (RsNotifyPopUp.height > 0) and ((RsNotifyPopUp_startPos.y - RsNotifyPopUp.height + 5) < currentPosY) do
|
|
(
|
|
RsNotifyPopUp.height -= RsNotifyPopUp_scrollIncrement
|
|
)
|
|
|
|
-- Move the form down (slower than it moved up)
|
|
RsNotifyPopUp.location.y += (RsNotifyPopUp_scrollIncrement / 2)
|
|
)
|
|
)
|
|
(RsNotifyPopUp_returning and (currentPosY == RsNotifyPopUp_startPos.y)):
|
|
(
|
|
RsNotifyPopUp_scrollTimer.stop()
|
|
RsNotifyPopUp_cleanup()
|
|
)
|
|
default:
|
|
(
|
|
-- Popup has reached its target position:
|
|
RsNotifyPopUp_scrollTimer.stop()
|
|
RsNotifyPopUp_closeTimer.start()
|
|
|
|
-- Resets close-timer (shouldn't be triggered by mousing over sub-controls)
|
|
fn mouseLeaveEvent =
|
|
(
|
|
if RsNotifyPopUp_closeTimer.enabled and not (RsNotifyPopUp.bounds.contains RsNotifyPopUp.mousePosition) do
|
|
(
|
|
RsNotifyPopUp_closeTimer.start()
|
|
)
|
|
)
|
|
|
|
dotNet.addEventHandler RsNotifyPopUp "mouseLeave" mouseLeaveEvent
|
|
)
|
|
)
|
|
)
|
|
catch
|
|
(
|
|
RsNotifyPopUp_scrollTimer.stop()
|
|
print "scrollTimerEvent fail"
|
|
print (getCurrentException())
|
|
)
|
|
)
|
|
|
|
-- Define timer-event to tell popup to go away once it's been onscreen for enough time (unless the mouse is over it)
|
|
fn closeTimerEvent =
|
|
(
|
|
try
|
|
(
|
|
if not (RsNotifyPopUp.bounds.contains RsNotifyPopUp.mousePosition) do
|
|
(
|
|
RsNotifyPopUp_returning = true
|
|
|
|
RsNotifyPopUp_closeTimer.stop()
|
|
RsNotifyPopUp_scrollTimer.start()
|
|
)
|
|
)
|
|
catch
|
|
(
|
|
RsNotifyPopUp_closeTimer.stop()
|
|
print "closeTimerEvent fail"
|
|
print (getCurrentException())
|
|
)
|
|
)
|
|
|
|
-- Cancel the popup-close timer if it gets focus:
|
|
fn popupClickedEvent =
|
|
(
|
|
RsNotifyPopUp_closeTimer.stop()
|
|
)
|
|
|
|
-- Run function if "Yes" button is pressed:
|
|
fn yesPressed =
|
|
(
|
|
local runFunc = RsNotifyPopUp_func
|
|
|
|
RsNotifyPopUp_cleanup()
|
|
|
|
if (runFunc != undefined) do
|
|
(
|
|
runFunc()
|
|
)
|
|
)
|
|
|
|
-- Select objs if "Select Objects" button is pressed:
|
|
fn selPressed =
|
|
(
|
|
RsNotifyPopUp_closeTimer.stop()
|
|
|
|
local selObjs = #()
|
|
|
|
case of
|
|
(
|
|
(RsNotifyPopUp_selFunc != undefined):
|
|
(
|
|
selObjs = for obj in objects where (RsNotifyPopUp_selFunc obj) collect obj
|
|
)
|
|
(isKindOf RsNotifyPopUp_objs array):
|
|
(
|
|
selObjs = for obj in RsNotifyPopUp_objs where isValidNode obj collect obj
|
|
)
|
|
)
|
|
|
|
undo "Select" on
|
|
(
|
|
clearSelection()
|
|
select selObjs
|
|
)
|
|
|
|
OK
|
|
)
|
|
|
|
local DNcolour = dotNetClass "System.Drawing.Color"
|
|
|
|
RsNotifyPopUp = RS_NoFocusDotNetForm()
|
|
RsNotifyPopUp.width = width
|
|
RsNotifyPopUp_returning = false
|
|
|
|
RsNotifyPopUp.controlBox = false
|
|
RsNotifyPopUp.backColor = DNcolour.FromArgb 255 255 200
|
|
RsNotifyPopUp.formBorderStyle = (dotNetClass "System.Windows.Forms.FormBorderStyle").FixedToolWindow
|
|
|
|
local graphics = RsNotifyPopUp.createGraphics()
|
|
|
|
-- Title label:
|
|
local titleLbl = dotNetObject "System.Windows.Forms.Label"
|
|
titleLbl.location.x = 4
|
|
titleLbl.location.y = 4
|
|
titleLbl.width = width - 8
|
|
|
|
local labelFont = dotnetobject "system.drawing.font" titleLbl.font.name (titleLbl.font.size + 2.5) (dotnetclass "system.drawing.fontstyle").bold
|
|
titleLbl.font = labelFont
|
|
titleLbl.text = replace_LF_with_CRLF title
|
|
|
|
titleLbl.height = (graphics.measureString titleLbl.text titleLbl.font titleLbl.width).height
|
|
|
|
RsNotifyPopUp.controls.add titleLbl
|
|
|
|
-- Notifier label:
|
|
local textLbl = dotNetObject "System.Windows.Forms.Label"
|
|
|
|
local bodyFont = dotnetobject "system.drawing.font" textLbl.font.name (textLbl.font.size + 1) (dotnetclass "system.drawing.fontstyle").Regular
|
|
textLbl.font = bodyFont
|
|
textLbl.text = replace_LF_with_CRLF text
|
|
|
|
textLbl.location.x = 4
|
|
textLbl.width = titleLbl.width
|
|
textLbl.location.y = titleLbl.location.y + titleLbl.height + 4
|
|
textLbl.height = (graphics.measureString textLbl.text textLbl.font titleLbl.width).height
|
|
|
|
RsNotifyPopUp.controls.add textLbl
|
|
|
|
local btnWidth = 50
|
|
local btnHeight = 20
|
|
|
|
-- BUTTONS --
|
|
|
|
-- OK/No button:
|
|
local closeBtn = dotNetObject "System.Windows.Forms.Button"
|
|
closeBtn.text = "OK"
|
|
closeBtn.width = btnWidth
|
|
closeBtn.height = btnHeight
|
|
|
|
local btnPos = [width - btnWidth - 6, textLbl.bottom + 12]
|
|
closeBtn.location.x = btnPos.x
|
|
closeBtn.location.y = btnPos.y
|
|
RsNotifyPopUp_targetHeight = closeBtn.bottom + 6
|
|
|
|
RsNotifyPopUp.controls.add closeBtn
|
|
dotnet.setLifetimeControl closeBtn #dotnet
|
|
dotNet.addEventHandler closeBtn "Click" RsNotifyPopUp_cleanup
|
|
|
|
-- "Yes" button runs function "func", if supplied:
|
|
if (func != unsupplied) do
|
|
(
|
|
closeBtn.text = "No"
|
|
|
|
local yesBtn = dotNetObject "System.Windows.Forms.Button"
|
|
yesBtn.text = "Yes"
|
|
yesBtn.width = btnWidth
|
|
yesBtn.height = btnHeight
|
|
yesBtn.location.x = (btnPos.x -= btnWidth)
|
|
yesBtn.location.y = btnPos.y
|
|
|
|
RsNotifyPopUp.controls.add yesBtn
|
|
dotnet.setLifetimeControl yesBtn #dotnet
|
|
dotNet.addEventHandler yesBtn "Click" yesPressed
|
|
|
|
RsNotifyPopUp_targetHeight = yesBtn.bottom + 6
|
|
)
|
|
|
|
-- If "objs" or "selFunc" is supplied, add a "Select Objects" button:
|
|
if (objs != unsupplied) or (selFunc != unsupplied) do
|
|
(
|
|
local selBtn = dotNetObject "System.Windows.Forms.Button"
|
|
selBtn.text = "Select Objects"
|
|
selBtn.height = btnHeight
|
|
selBtn.width = 90
|
|
selBtn.location.x = (btnPos.x -= selBtn.width)
|
|
selBtn.location.y = btnPos.y
|
|
|
|
RsNotifyPopUp.controls.add selBtn
|
|
dotnet.setLifetimeControl selBtn #dotnet
|
|
dotNet.addEventHandler selBtn "Click" selPressed
|
|
)
|
|
|
|
-- END BUTTONS --
|
|
|
|
local windowPos = getMAXWindowPos()
|
|
local windowSize = getMAXWindowSize()
|
|
|
|
RsNotifyPopUp_startPos = windowPos + windowSize - [width + 14, 14]
|
|
RsNotifyPopUp_targetYPos = windowPos.y + windowSize.y - RsNotifyPopUp_targetHeight - 14
|
|
RsNotifyPopUp.height = 0
|
|
|
|
-- If box is set to instantly appear, it's moved up all in one go:
|
|
-- (it's first drawn off-screen though, as otherwise controls draw in blank to begin with)
|
|
if (instantly) do
|
|
(
|
|
scrollIncrement = RsNotifyPopUp_targetHeight
|
|
)
|
|
|
|
RsNotifyPopUp.Show (RS_dotNetMaxHWND())
|
|
RsNotifyPopUp.location.x = RsNotifyPopUp_startPos.x
|
|
RsNotifyPopUp.location.y = RsNotifyPopUp_startPos.y
|
|
|
|
-- Scroll-timer:
|
|
RsNotifyPopUp_scrollTimer = dotNetObject "System.Windows.Forms.Timer"
|
|
|
|
RsNotifyPopUp_scrollIncrement = scrollIncrement
|
|
RsNotifyPopUp_scrollTimer.interval = scrollInterval
|
|
|
|
-- Wait-timer:
|
|
RsNotifyPopUp_closeTimer = dotNetObject "System.Windows.Forms.Timer"
|
|
RsNotifyPopUp_closeTimer.interval = timeOut
|
|
|
|
--Add Event Handlers:
|
|
dotNet.addEventHandler RsNotifyPopUp_scrollTimer "Tick" scrollTimerEvent
|
|
dotNet.addEventHandler RsNotifyPopUp_closeTimer "Tick" closeTimerEvent
|
|
dotNet.addEventHandler RsNotifyPopUp "Click" popupClickedEvent
|
|
|
|
RsNotifyPopUp_scrollTimer.start()
|
|
|
|
return RsNotifyPopUp
|
|
)
|
|
|
|
--RsNotifyPopUp_create text:"Text" title:"Title" func:testPress
|