Son-Guhun / Titan-Land-Lands-of-Plenty

A WC3 sandbox roleplaying map inspired by those that came before.
MIT License
10 stars 0 forks source link

Detecting Screen Mouse Position using as few frames as possible #195

Open Son-Guhun opened 3 years ago

Son-Guhun commented 3 years ago

Assumptions

Algorithm

Son-Guhun commented 3 years ago

Results

Code

Library

library MouseDetect
//! textmacro ThisLib_GetterSetter takes type, name
    static $type$ array array$name$

    method get$name$ takes integer i, integer j returns $type$
        return array$name$[this*OFFSET + i*MAX_SIZE + j]
    endmethod

    private method set$name$ takes integer i, integer j, $type$ val returns nothing
        set array$name$[this*OFFSET + i*MAX_SIZE + j] = val
    endmethod
//! endtextmacro

struct ScreenBlocks
    public  static constant integer MAX_SIZE = 9
    private static constant integer OFFSET = MAX_SIZE*MAX_SIZE

    //! runtextmacro  ThisLib_GetterSetter("framehandle", "Frame")
    //! runtextmacro  ThisLib_GetterSetter("framehandle", "Tooltip")

    static method create takes integer width, integer height, real x0, real y0, real x, real y returns thistype
        local thistype this = allocate()
        local integer i = 0
        local integer j = 0
        local framehandle frame
        local framehandle tooltip

        loop
            exitwhen i >= height
            loop 
                set frame = BlzCreateFrameByType("FRAME", "FaceFrame", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0) // BlzCreateFrame("ScriptDialogButton", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
                set tooltip = BlzCreateFrameByType("BACKDROP", "FaceButtonIcon", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0) //  BlzCreateFrame("ScriptDialogButton", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
                // call BlzFrameSetTexture(frame, "ReplaceableTextures\\CommandButtons\\BTNSelectHeroOn", 0, true)
                call BlzFrameSetTooltip(frame, tooltip)
                call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, .getFrame(i, j-1), FRAMEPOINT_RIGHT, 0., 0.)
                call BlzFrameSetSize(tooltip, (x - x0)/width, (y0 - y)/height)
                call BlzFrameSetAbsPoint(tooltip, FRAMEPOINT_CENTER, 0.4, 0.3)
                call BlzFrameSetTexture(tooltip, "ReplaceableTextures\\CommandButtons\\BTNSelectHeroOn", 0, true)
                call BlzFrameSetAlpha(frame, 127)
                call BlzFrameSetEnable(frame, false)

                /*if j > 0 then
                    call BlzFrameSetPoint(.getFrame(i, j-1), FRAMEPOINT_RIGHT, frame, FRAMEPOINT_LEFT, 0., 0.)
                endif*/
                call BlzFrameSetSize(frame, (x - x0)/width, (y0 - y)/height)
                call .setFrame(i, j, frame)
                call .setTooltip(i, j, tooltip)

                set j = j + 1
                if j == width then
                    call BlzFrameSetAbsPoint(.getFrame(i,j-1), FRAMEPOINT_RIGHT, x, y)
                    exitwhen true
                endif
            endloop

            if i > 0 then
                call BlzFrameSetPoint(.getFrame(i,0), FRAMEPOINT_TOP, .getFrame(i-1, 0), FRAMEPOINT_BOTTOM, 0., 0.)
            else
                call BlzFrameSetAbsPoint(.getFrame(0,0), FRAMEPOINT_TOPLEFT, x0, y0)
            endif
            set i = i + 1
            set j = 0
        endloop

        // call BlzFrameSetPoint(.getFrame(0, height-1), FRAMEPOINT_BOTTOMLEFT, leftBorderFrame, FRAMEPOINT_BOTTOMRIGHT, 0., 0.)

        return this
    endmethod

endstruct

endlibrary

Testing

globals
    ScreenBlocks bigBlocks
    ScreenBlocks smallBlocks
endglobals

function onTimer2 takes nothing returns nothing
   local integer i = 0
   local integer j = 0

   loop
       exitwhen i == 8
       loop
           exitwhen j == 8 or BlzFrameIsVisible(bigBlocks.getTooltip(i, j))
           set j = j + 1
       endloop
       exitwhen BlzFrameIsVisible(bigBlocks.getTooltip(i, j))
       set i = i + 1
       set j = 0
   endloop

   call BJDebugMsg("i / j: " + I2S(i) + " / " + I2S(j))
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_004 takes nothing returns nothing
   set bigBlocks = ScreenBlocks.create(8, 8, 0., 0.6, 0.8, 0.)
   set smallBlocks = ScreenBlocks.create(8, 8, 0., 0.6, 0.8/8, 7*0.6/8)

   if GetHandleId(bigBlocks.getFrame(0, 0)) > 0 then
      call TimerStart(CreateTimer(), 1/32., true, function onTimer2)
   endif

   call BJDebugMsg(I2S(bigBlocks))
   call BJDebugMsg(I2S(smallBlocks))
   // call BlzFrameSetVisible(bigBlocks.getFrame(0,7), false)
endfunction