Search code examples
luatextureswxlua

WxLua GUI 2d mappinp


Ok guys so I’m trying to make a 2d map (a literal map of my game) for my gui. When in game I exported the terrain data to an external lua file which looks like this Info = { 1 = { Color = “blue”, x = 0, y = 0 }, ect ect...} basically one big array. My gui reads this file and wxDrawcircle and place pixel size colored dots at the coordinates. This all works and creates a nice looking map but the problem is when I go to click or do anything it freezes and looks like the GUI can’t handle all those dots. It almost seems like when ever I click the GUI refreshes and re renders all those dots again. So my question is should I make a texture instead or is there a way my GUI can render the map once and not over and over again like it’s refreshing it’s self?

UPDATE: Thanks for the feedback guys really improved the speed at which it loads up. But I added if canrun then so it will only run once because I found out everytime you moved the scroll wheel it regenerated the whole map which was causing the crash. So if there is a workaround to keep the map from disappearing when you scroll up or down that would work.

My GUI. UPDATED

    package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;"
require("wx")

frame = nil
canrun = true

Panle1_Send_It_Button = 100
Panle1_Static_Box_1 = 101
Panle1_Static_Box_2 = 102
Panle1_Static_Box_3 = 103
Panle1_TextCtrl_1 = 104
Panle1_TextCtrl_2 = 105

P1_SB1_Selected = -1
P1_SB2_Selected = -1
P1_SB3_Selected = -1

function HandleEvents(event)
   local name = event:GetEventObject():DynamicCast("wxWindow"):GetName()
    frame:SetStatusText(string.format("%s - You are on the %d '%s'", name, event:GetSelection(), event:GetString()), 0)
    if event:GetSelection() == 3 then canrun = true print("PRINT2") end
end


local _T = function(s) return s end
local wxT = function(s) return s end

function GetColor(IC,Type)
    if IC == "Green" or IC == "Black" then
            if Type == 0 then 
                --Pix = wx.wxBrush(wx.wxColour(226,204,113),wx.wxSOLID
                Pix = wx.wxGREEN_BRUSH
            else
                Pix = wx.wxGREEN_PEN
            end
        else
            if IC == "Blue" then
                if Type == 0 then 
                    Pix = wx.wxCYAN_BRUSH
                else
                    Pix = wx.wxCYAN_PEN
                end
            else
               if Type == 0 then 
                    Pix = wx.wxGREY_BRUSH
               else
                    Pix = wx.wxGREY_PEN
                end
            end
        end
    return Pix
end

function OnPaint(event)
    local dc = wx.wxPaintDC(sw)
    sw:PrepareDC( dc )
    Number = 1
    if canrun then
    canrun = false
    print("PAINT")
    for i = 22,1,-1 do 
        local FileName = string.format("PixleData%s.lua",Number)
        dofile(FileName)
        for i, GroupF in ipairs(Info) do 
            local Data = Info[i]
            local Color = Data["Color"]
            local Xpos = Data["Xp"]
            local Ypos = Data["Yp"]
            local PixColor = GetColor(Color,0)
            local PenColor = GetColor(Color,1)

            dc:SetPen( PenColor )
            dc:SetBrush( PixColor )
            dc:DrawPoint( Xpos, Ypos)
        end
        Number = Number+1
    end
    dc:delete()
    end
end

function main()
    -- create the hierarchy: frame -> notebook
    frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, "DCS Support Tablet",wx.wxDefaultPosition, wx.wxSize(900, 600))
    frame:CreateStatusBar(1)
    frame:SetStatusText("", 0)
    T = frame

    local notebook = wx.wxNotebook(frame, wx.wxID_ANY,
                                   wx.wxDefaultPosition, wx.wxDefaultSize)
                                   --wx.wxNB_BOTTOM)

    -- create first panel in the notebook control
    local panel1 = wx.wxPanel(notebook, wx.wxID_ANY)
    local sizer1 = wx.wxBoxSizer(wx.wxVERTICAL)
    local choice = wx.wxChoice(panel1, Panle1_Static_Box_1,
                               wx.wxDefaultPosition, wx.wxDefaultSize,
                               {"Al Dhafra AB", "Al Maktoum Intl", "Sharjah Intl", "Fujairah Intl"})

    local choiceBoxStaticBox = wx.wxStaticBox( panel1, wx.wxID_ANY, "Deployment From")
    local choiceBoxStaticBoxSizer = wx.wxStaticBoxSizer( choiceBoxStaticBox, wx.wxVERTICAL );
    choiceBoxStaticBoxSizer:Add(choice, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)

    local choice2 = wx.wxChoice(panel1, Panle1_Static_Box_2,
                               wx.wxDefaultPosition, wx.wxDefaultSize,
                               {"Carrier", "Al Dhafra AB", "Al Maktoum Intl", "Sharjah Intl", "Fujairah Intl", "Grid Cordinates (For FOBs Only)"})

    local choiceBoxStaticBox2 = wx.wxStaticBox( panel1, wx.wxID_ANY, "Attack Location")
    local choiceBoxStaticBoxSizer2 = wx.wxStaticBoxSizer( choiceBoxStaticBox2, wx.wxVERTICAL );
    choiceBoxStaticBoxSizer2:Add(choice2, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)

    local choice3 = wx.wxChoice(panel1, Panle1_Static_Box_3,
                               wx.wxDefaultPosition, wx.wxDefaultSize,
                               {"A-10C","F/A-18C","M1A2 MBT"})

    local choiceBoxStaticBox3 = wx.wxStaticBox( panel1, wx.wxID_ANY, "Unit To Be Deployed")
    local choiceBoxStaticBoxSizer3 = wx.wxStaticBoxSizer( choiceBoxStaticBox3, wx.wxVERTICAL );
    choiceBoxStaticBoxSizer3:Add(choice3, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)

    local staticText = wx.wxStaticText( panel1, wx.wxID_ANY, "North", wx.wxPoint(7,194))
    local textCtrl   = wx.wxTextCtrl( panel1, Panle1_TextCtrl_1, "000", wx.wxPoint(35,190), wx.wxDefaultSize, wx.wxTE_PROCESS_ENTER )
    local text_w, text_h = textCtrl:GetTextExtent("00000.00000")
    textCtrl:SetInitialSize(wx.wxSize(text_w, -1))

    local staticText2 = wx.wxStaticText( panel1, wx.wxID_ANY, "East", wx.wxPoint(105,194))
    local textCtrl2   = wx.wxTextCtrl( panel1, Panle1_TextCtrl_2, "000", wx.wxPoint(128,190), wx.wxDefaultSize, wx.wxTE_PROCESS_ENTER )
    local text_w2, text_h2 = textCtrl2:GetTextExtent("00000.00000")
    textCtrl2:SetInitialSize(wx.wxSize(text_w2, -1))

    local staticText3 = wx.wxStaticText( panel1, wx.wxID_ANY, "Available Resources At Selected Base - 500/", wx.wxPoint(200,194))
    local staticText4 = wx.wxStaticText( panel1, wx.wxID_ANY, "Selected Unit Cost - 100", wx.wxPoint(415,194))
    button = wx.wxButton( panel1, Panle1_Send_It_Button, "Confirm",wx.wxPoint(245,242),wx.wxSize(50, 20),0)

    sizer1:Add(choiceBoxStaticBoxSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)
    sizer1:Add(choiceBoxStaticBoxSizer2, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)
    sizer1:Add(choiceBoxStaticBoxSizer3, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)
    panel1:SetSizer(sizer1)
    sizer1:SetSizeHints(panel1)
    notebook:AddPage(panel1, "Deployment")

    -- create second panel in the notebook control
    local panel2 = wx.wxPanel(notebook, wx.wxID_ANY)
    local sizer2 = wx.wxBoxSizer(wx.wxVERTICAL)

    local choice = wx.wxChoice(panel2, wx.wxID_ANY,
                               wx.wxDefaultPosition, wx.wxDefaultSize,
                               {"Al Dhafra AB", "Al Maktoum Intl", "Sharjah Intl", "Fujairah Intl"})

    local choiceBoxStaticBox = wx.wxStaticBox( panel2, wx.wxID_ANY, "Deployment From")
    local choiceBoxStaticBoxSizer = wx.wxStaticBoxSizer( choiceBoxStaticBox, wx.wxVERTICAL );
    choiceBoxStaticBoxSizer:Add(choice, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)

   local choice2 = wx.wxChoice(panel2, wx.wxID_ANY,
                               wx.wxDefaultPosition, wx.wxDefaultSize,
                               {"A-10C","F/A-18C","M1A2 MBT"})

    local choiceBoxStaticBox2 = wx.wxStaticBox( panel2, wx.wxID_ANY, "Unit To Be Deployed")
    local choiceBoxStaticBoxSizer2 = wx.wxStaticBoxSizer( choiceBoxStaticBox2, wx.wxVERTICAL );
    choiceBoxStaticBoxSizer2:Add(choice2, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)

    sizer2:Add(choiceBoxStaticBoxSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)
    sizer2:Add(choiceBoxStaticBoxSizer2, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 5)
    panel2:SetSizer(sizer2)
    sizer2:SetSizeHints(panel2)
    notebook:AddPage(panel2, "Defense")

    local panel3 = wx.wxPanel(notebook, wx.wxID_ANY)
    notebook:AddPage(panel3, "Main H.Q.")

    panel4 = wx.wxPanel(notebook, 664)
    notebook:AddPage(panel4, "Mission Information")

    sw = wx.wxScrolledWindow( panel4, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxSize(900, 600),wx.wxHSCROLL + wx.wxVSCROLL)
    sw:SetScrollbars(15, 15, 900, 600, 0, 0, false)
    sw:Connect(wx.wxEVT_PAINT, OnPaint)

     frame:SetSizeHints(notebook:GetBestSize():GetWidth(),notebook:GetBestSize():GetHeight())

    -- typically you will give a control a specific window id and connect an
    -- event handler for that id, in this case respond to any id
    frame:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, HandleEvents)

    frame:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_RADIOBOX_SELECTED, HandleEvents)
    frame:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_LISTBOX_SELECTED, HandleEvents)

    frame:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_COMBOBOX_SELECTED, HandleEvents)
    frame:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_CHOICE_SELECTED, HandleEvents)
    frame:Connect(wx.wxID_ANY, wx.wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, HandleEvents)

    frame:Connect(Panle1_Static_Box_1, wx.wxEVT_COMMAND_CHOICE_SELECTED, 
        function(event)
            P1_SB1_Selected = event:GetSelection()
    end)

    frame:Connect(Panle1_Static_Box_2, wx.wxEVT_COMMAND_CHOICE_SELECTED, 
        function(event)
            P1_SB2_Selected = event:GetSelection()
    end)

    frame:Connect(Panle1_Static_Box_3, wx.wxEVT_COMMAND_CHOICE_SELECTED, 
        function(event)
            P1_SB3_Selected = event:GetSelection()
    end)

    frame:Connect(Panle1_Send_It_Button, wx.wxEVT_COMMAND_BUTTON_CLICKED,
        function(event)
            if P1_SB1_Selected == -1 or P1_SB2_Selected == -1 or P1_SB3_Selected == -1 then
                wx.wxMessageBox("Missing Entry\n", "Try Agian Commander", wx.wxOK + wx.wxICON_INFORMATION, frame)
            else
                local MissionVariables = string.format( "STCost = %s STSpawnFrom = %s STAttackLocation = %s STUnitType = %s STCanSpawn = true", 100,P1_SB1_Selected,P1_SB2_Selected+1,P1_SB3_Selected )
                local DataFile = io.open("Data.lua", "w")
                DataFile:write(MissionVariables)
                DataFile:close()
            end
    end)

    frame:Show(true)
end
main()
wx.wxGetApp():MainLoop()

This is the map it creates its a little longer down but when the scroll wheel is moved it disappears


Solution

  • There are several things you can improve:

    1. You are creating dc for each dot. This is hugely inefficient, as you only need to create it once before the loops (in fact you do this, but don't use it).
    2. Same for deleting dc; only do it once after the loop
    3. You keep reloading the files multiple times; load them ones and save the results in a table, then use it as needed.
    4. You are resetting pen and brush even when the colors don't change; to minimize the changes, you may want to group them by color.
    5. You draw circle with 1 dot radius. Why not use DrawPoint instead?

    So my question is should I make a texture instead or is there a way my GUI can render the map once and not over and over again like it’s refreshing it’s self?

    Yes, you can save what you are drawing to a bitmap and then draw the bitmap itself without spending time to draw its components. Your OnPaint handler will look like this:

    local function onPaint()
      local dc = wx.wxPaintDC(frame)
      dc:DrawBitmap(bitmap, 0, 0, true)
      dc:delete()
    end
    

    Your drawing will draw on the bitmap when needed:

    mdc:SelectObject(bitmap)
    mdc:SetPen(WHATEVER)
    mdc:DrawPoint(x, y)
    mdc:SelectObject(wx.wxNullBitmap)
    

    where mdc=wx.wxMemoryDC().