Don't like ads? PRO users don't see any ads ;-)
Guest

gui_map_editor.lua

By: a guest on Aug 11th, 2012  |  syntax: Lua  |  size: 29.17 KB  |  hits: 11  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. --------------------------------------------------------------------------------
  2. --------------------------------------------------------------------------------
  3. function widget:GetInfo()
  4.   return {
  5.     name      = "Map Editor",
  6.     version   = 0.9,
  7.     desc      = "Map Drawing Widget(Chili)",
  8.     author    = "Pako",
  9.     date      = "2012.05.24 - 2012.08.07",
  10.     license   = "GNU GPL, v2 or later",
  11.     layer     = 100000,
  12.     enabled   = false
  13.   }
  14. end
  15.  
  16. --NOTE to edit specular or detail ditribution textures etc. you need a small hacky patch and map definition needs some references to enable the textures
  17. --NOTE select a painting texture by double clickin with right mouse button--(you can easily "update" the texture mode(linear,nearest,etc.) just by dblcking again )
  18. --TODO BUG if the painting texture is empty it is mostly white but there is some crap in there
  19.  
  20. --TODO
  21. --fix out of map drawing (drawing on edge)
  22. --eraser and clone tool--clone works easily within the same texture?-some GL doc said no...but seems to work fine with my nvidia
  23. --erasing to original texture always needs to get the original map textures which seems to be randomly bugged
  24.  
  25. --make trackbars show the value and double clicking opens an editbox to set it raw(even outside the scale)
  26.  
  27. --myMapfilename(use as the folder) editbox, import export --import is fairly easy
  28. --color picker grid--clicking the big square in current color picker shows a grid window
  29. --include blueprint and editor to edit the values(partially edit in realtime with /commands?)
  30. --change editing mode and blend mode to lists
  31.  
  32. --TODO BUG everything seems randomly inverted or mirrored
  33. --TODO some indentation? do it by compruter, human is not and indentation machine and Python is for redards
  34.  
  35. --TODO figure out how to generate the map file and do a little help button&textbox which contains the instructions
  36.  
  37. local gl = gl
  38. local max = math.max
  39. local floor = math.floor
  40. local min = math.min
  41.  
  42.  
  43. --------------------------------------------------------------------------------
  44. --------------------------------------------------------------------------------
  45.  
  46.  
  47. local BIG_TEX_SIZE = 128*8 --bigTexSize      = (SQUARE_SIZE * bigSquareSize);
  48. local SPECULAR_TEX_SIZE = 1024
  49. local TEXS_X = math.floor(Game.mapSizeX/BIG_TEX_SIZE)
  50. local TEXS_Z = math.floor(Game.mapSizeZ/BIG_TEX_SIZE)
  51.  
  52.  
  53.  
  54. local mainDir = 'mapEditor/'
  55.  
  56. local myTex
  57. local mapTexSQ
  58.  
  59. local mapFBOtextures = {}
  60.  
  61. local modifiedFBOtextures = {} --only for faster exporting
  62.  
  63. local myTexShader
  64.  
  65. local windowImageList
  66. local windowSettingList
  67. local colorBars
  68. local penStepCtrl
  69. local zoomCtrl
  70.  
  71. local penStep = 100
  72. local penTimeStep = 0.3 --should be more than mouse click duration?-
  73. local projectPen = false
  74. local penZoom = 1.0
  75. local texturePaintZoom = 1.0
  76. local texturePaintOffsetX,texturePaintOffsetZ = 0,0 --BUG ged?
  77.  
  78. local showPen = true
  79.  
  80. local penTexture
  81. local paintTexture = false --always set to false or to empty texture
  82.  
  83. local eraser = false --erasing mode
  84.  
  85. local overTex
  86.  
  87. local exportNOW = false
  88.  
  89.  
  90. local specularEditing = false -- -1 to -5
  91. local editingLayers = {
  92.   ["Map Texture"] = false,
  93.     ["SpecularTexture"] = -1,
  94.     ["skyReflectModTex"] = -2,
  95.     ["detailNormalTex"] = -3,
  96.     ["lightEmissionTex"] = -4,
  97.     ["parallaxHeightTex"] = -5,
  98.     ["splatDetailTex"] = -6,
  99.     ["splatDistrTex"] = -7,
  100.     }
  101. local mapSpecularTextures = {}
  102.  
  103.  
  104. local penBlenders = {
  105.   --'from'
  106. --// 2010 Kevin Bjorke http://www.botzilla.com
  107. --// Uses Processing & the GLGraphics library
  108.         ["BlendNormal"] = [[mix(penColor,mapColor,penColor.a);]],
  109.      
  110.         ["BlendAdd"] = [[mix((mapColor+penColor),mapColor,penColor.a);]],
  111.        
  112.         ["BlendColorBurn"] = [[mix(1.0-(1.0-mapColor)/penColor,mapColor,penColor.a);]],
  113.        
  114.         ["BlendColorDodge"] = [[mix(mapColor/(1.0-penColor),mapColor,penColor.a);]],
  115.  
  116.         ["BlendColor"] = [[mix(sqrt(dot(mapColor.rgb,mapColor.rgb)) * normalize(penColor),mapColor,penColor.a);]],
  117.        
  118.         ["BlendDarken"] = [[mix(min(mapColor,penColor),mapColor,penColor.a);]],
  119.        
  120.         ["BlendDifference"] = [[mix(abs(penColor-mapColor),mapColor,penColor.a);]],
  121.        
  122.         ["BlendExclusion"] = [[mix(penColor+mapColor-(2.0*penColor*mapColor),mapColor,penColor.a);]],
  123.  
  124.         ["BlendHardLight"] = [[mix(lerp(2.0 * mapColor * penColor,1.0 - 2.0*(1.0-penColor)*(1.0-mapColor),min(1.0,max(0.0,10.0*(dot(vec4(0.25,0.65,0.1,0.0),penColor)- 0.45)))),mapColor,penColor.a);]],
  125.        
  126.         ["BlendInverseDifference"] = [[mix(1.0-abs(mapColor-penColor),mapColor,penColor.a);]],
  127.  
  128.         ["BlendLighten"] = [[mix(max(penColor,mapColor),mapColor,penColor.a);]],
  129.        
  130.         ["BlendLuminance"] = [[mix(dot(penColor,vec4(0.25,0.65,0.1,0.0))*normalize(mapColor),mapColor,penColor.a);]],
  131.        
  132.         ["BlendMultiply"] = [[mix(penColor*mapColor,mapColor,penColor.a);]],
  133.        
  134.         ["BlendOverlay"] = [[mix(lerp(2.0 * mapColor * penColor,1.0 - 2.0*(1.0-penColor)*(1.0-mapColor),min(1.0,max(0.0,10.0*(dot(vec4(0.25,0.65,0.1,0.0),mapColor)- 0.45)))),mapColor,penColor.a);]],
  135.        
  136.         ["BlendPremultiplied"] = [[vec4(penColor.rgb + (1.0-penColor.a)*mapColor.rgb, (penColor.a+mapColor.a));]],
  137.  
  138.         ["BlendScreen"] = [[mix(1.0-(1.0-mapColor)*(1.0-penColor),mapColor,penColor.a);]],
  139.        
  140.         ["BlendSoftLight"] = [[mix(2.0*mapColor*penColor+mapColor*mapColor-2.0*mapColor*mapColor*penColor,mapColor,penColor.a);]],
  141.        
  142.         ["BlendSubtract"] = [[mix(mapColor-penColor,mapColor,penColor.a);]],
  143.        
  144.         ["BlendUnmultiplied"] = [[mix(penColor,mapColor,penColor.a);]],
  145.        
  146.         ["BlendRAW"] = [[penColor;]], --//TODO make custom shaders for specular textures
  147. }
  148.   --(Blend.*) = (.*;)
  149.   --["\1"] = [[\2]],
  150.        
  151.         local shaderFragStr = [[                                       
  152.  
  153. uniform sampler2D mapTex;
  154. uniform sampler2D penTex;
  155. uniform sampler2D paintTex;
  156.  
  157. vec4 mix(vec4 penColor, vec4 mapColor,float alpha) {
  158.     return vec4(penColor.rgb*alpha + mapColor.rgb*(1.0-alpha), 1.0);
  159. }
  160.  
  161. void main(void)
  162. {
  163.         vec4 mapColor = texture2D(mapTex,gl_TexCoord[0].st);
  164.         vec4 penColor = texture2D(penTex,gl_TexCoord[1].st);
  165.         vec4 texColor = texture2D(paintTex,gl_TexCoord[2].st);
  166.        
  167.         penColor = (gl_Color*penColor*texColor);
  168.        
  169.         vec4 color = %s  //mix(penColor,mapColor,penColor.a);
  170.         //color.a = 1.0; //??
  171.        
  172.         gl_FragColor = color;
  173. }
  174. ]]
  175.  
  176. local shaderTemplate = {
  177.                                         fragment =
  178.         string.format(shaderFragStr,penBlenders["BlendNormal"]),
  179.                                         uniformInt = {
  180.                                                 mapTex = 0,
  181.                                                 penTex = 1,
  182.                                                 paintTex = 2,
  183.                                         },
  184.                                 }
  185.        
  186. function widget:Initialize()
  187.  
  188.  
  189.   Spring.CreateDir(mainDir)
  190.  
  191.  
  192.         local Chili = WG.Chili
  193.       local screen0 = Chili.Screen0
  194.  
  195.         local Image = Chili.Image
  196.         local Button = Chili.Button
  197.         local Label = Chili.Label
  198.  
  199.        
  200.   windowImageList = Chili.Window:New{
  201.   x = 0,
  202.   y = "40%",
  203.   width = (64+10)*3, --"15%",
  204.   height = "60%",
  205.   parent = screen0,
  206. }
  207.  
  208.   local imgC = {}
  209.   for k,v in pairs {
  210.     ['n'] = "nearest",
  211.     ['l'] = "linear",
  212.     ['a'] = "aniso",
  213.     ['i'] = "invert",
  214.     ['g'] = "greyed",
  215.     ['c'] = "clamped",
  216.     ['b'] = "border",} do
  217.     imgC[#imgC+1] =                 Chili.Checkbox:New{
  218.                         caption=v,
  219.                         checked = false,
  220.                         textureLTset = false,
  221.                         OnChange = { function(self, checked)
  222.                                 self.textureLTset = checked and k
  223.                         end }}
  224.   end
  225.  
  226.   Chili.StackPanel:New{
  227.     x=0,y="80%",
  228.   width = "100%",
  229.   height = "20%",
  230.   parent = windowImageList,
  231.   children = imgC}
  232.  
  233.     local function GetParentDir(dir)
  234.   dir = dir:gsub("\\", "/")
  235.   local lastChar = dir:sub(-1)
  236.   if (lastChar == "/") then
  237.     dir = dir:sub(1,-2)
  238.   end
  239.   local pos,b,e,match,init,n = 1,1,1,1,0,0
  240.   repeat
  241.     pos,init,n = b,init+1,n+1
  242.     b,init,match = dir:find("/",init,true)
  243.   until (not b)
  244.   if (n==1) then
  245.     return ''
  246.   else
  247.     return dir:sub(1,pos)
  248.   end
  249. end
  250.  
  251. Chili.ScrollPanel:New{
  252.   width = "100%",
  253.   height = "80%",
  254.   --anchors = {top=true,left=true,bottom=true,right=true},
  255.   parent = windowImageList,  
  256.   children =    {Chili.ImageListView:New{
  257.       name = "MyStencilListView",
  258.       width = "100%",
  259.       height = "100%",
  260. --      anchors = {top=true,left=true,bottom=true,right=true},
  261.       --dir = mainDir,
  262.       --dir = "LuaUI/Images/",
  263.       dir = "bitmaps/",
  264.       OnSelectItem = {
  265.         function(obj,itemIdx,selected)
  266.           --Spring.Echo("image selected ",itemIdx,selected, obj.children[itemIdx] and obj.children[itemIdx].file)
  267.         end,
  268.       },
  269.       OnDblClickItem = {
  270.         function(obj,itemPath,_,button)
  271.         local prefix
  272.         for _,v in pairs(imgC) do
  273.           if v.textureLTset then
  274.             prefix = prefix and prefix..(v.textureLTset) or ":"..(v.textureLTset)
  275.           end
  276.         end
  277.         prefix = prefix and prefix..":" or ""
  278.           if button == 1 then
  279.             Spring.Echo("Pen selected",itemPath)
  280.             penTexture =  prefix.. tostring(itemPath)
  281.           elseif button == 3 then
  282.                 Spring.Echo("Texture selected",itemPath)
  283.             paintTexture =  prefix.. tostring(itemPath)
  284.             eraser = false
  285.           end
  286.         end,
  287.       },
  288.       MouseDblClick = function(self,x,y,button)
  289.   local cx,cy = self:LocalToClient(x,y)
  290.   local itemIdx = self:GetItemIndexAt(cx,cy)
  291.  
  292.   if (itemIdx<0) then return end
  293.  
  294.   if (itemIdx==1) then
  295.     self:SetDir(GetParentDir(self.dir))
  296.     return self
  297.   end
  298.  
  299.   if (itemIdx<=self._dirsNum+1) then
  300.     self:SetDir(self._dirList[itemIdx-1])
  301.     return self
  302.   else
  303.     self:CallListeners(self.OnDblClickItem, self.items[itemIdx], itemIdx, button)
  304.     return self
  305.   end
  306. end,
  307.     }},
  308.     --Button:New{width = 410, height = 400, anchors = {top=true,left=true,bottom=true,right=true}},
  309.  
  310. }
  311. colorBars = Chili.Colorbars:New{
  312.       --x     = "100%",
  313.       --y     = "100%",
  314.   width = "100%",
  315.       height = 80,
  316.     }
  317.    
  318.     penStepCtrl = Chili.Trackbar:New{
  319.                                         width = "100%",
  320.           height=30,
  321.                                         value = 10,
  322.                                         trackColor = {1,1,0,1},
  323.                                         min=0,
  324.                                         max=100,
  325.                                         step= 1,
  326.                                         tooltip="Pen stepping (seconds/100 and pixels)",
  327.           OnChange = {function(self,value)
  328.                                         penStep = value
  329.                                         penTimeStep = value/100
  330.                                         end,
  331.                                         }                               }
  332.                                             zoomCtrl = Chili.Trackbar:New{
  333.                                         width = "100%",
  334.           height=30,
  335.                                         value = 1,
  336.                                         min=0.1,
  337.                                         max=100,
  338.                                         step= 0.1,
  339.                                         tooltip="Pen Zooming",
  340.           OnChange = {function(self,value)
  341.                                         penZoom = value
  342.                                         end,
  343.                                         }                               }
  344.                                        
  345.                                         local texturePaintScale =                                             Chili.Trackbar:New{
  346.                                         width = "100%",
  347.           height=30,
  348.                                         value = 1,
  349.                                         min=0.01,
  350.                                         max=10,
  351.                                         step= 0.01,
  352.                                         tooltip="Texture painting scale",
  353.           OnChange = {function(self,value)
  354.                                         texturePaintZoom = value
  355.                                         end,
  356.                                         }                               }
  357.                                        
  358.                                         local texturePaintOX =                                        Chili.Trackbar:New{
  359.                                         width = "100%",
  360.           height=20,
  361.                                         value = 0,
  362.                                         min=-1,
  363.                                         max=1,
  364.                                         step= 0.01,
  365.                                         tooltip="Texture painting offset X",
  366.           OnChange = {function(self,value)
  367.                                         texturePaintOffsetX = value
  368.                                         end,
  369.                                         }                               }
  370.                                                                                 local texturePaintOZ =                                        Chili.Trackbar:New{
  371.                                         width = "100%",
  372.           height=20,
  373.                                         value = 0,
  374.                                         min=-1,
  375.                                         max=1,
  376.                                         step= 0.01,
  377.                                         tooltip="Texture painting offset Z",
  378.           OnChange = {function(self,value)
  379.                                         texturePaintOffsetZ = value
  380.                                         end,
  381.                                         }                               }
  382.                                        
  383.   windowSettingList = Chili.Window:New{
  384.   x = windowImageList.width, -- 300,
  385.   y = "40%",
  386.   width = "20%",
  387.   --height = "40%",
  388.   autosize = true,
  389.   parent = screen0,
  390.   children = {Chili.StackPanel:New{
  391.   width = 250,
  392.   --height = "100%",
  393.                                         resizeItems = false,
  394.                                         centerItems = false,
  395.                                         autosize = true,
  396.   children = {
  397.    
  398.     Chili.Button:New{width = "100%",
  399.                         caption=("Editing Mode: ")..'Map texture',
  400.                         editingItr = "Map Texture",
  401.                         tooltip = "Select which texture to edit",
  402.                         OnClick = { function(self)
  403.                                 self.editingItr, specularEditing = next(editingLayers, self.editingItr)
  404.                                 if self.editingItr == nil then --around
  405.                                   self.editingItr, specularEditing = next(editingLayers, self.editingItr)
  406.                                 end
  407.                                 Spring.Echo(self.editingItr,specularEditing)
  408.                                   self._down = false
  409.   self.state = 'normal'
  410.   self:SetCaption( ("Editing Mode: ").. tostring(self.editingItr))
  411.                         end },
  412.                 },
  413.                     Chili.Button:New{width = "100%",
  414.                         caption=("Blend shader mode: ").."BlendNormal",
  415.                         editingItr = "BlendNormal",
  416.                         tooltip = "Reconstruct a shader for texture blending",
  417.                         OnClick = { function(self)
  418.                           local shadeString
  419.                                 self.editingItr, shadeString = next(penBlenders, self.editingItr)
  420.                                                                 if self.editingItr == nil then --around
  421.                                   self.editingItr, shadeString = next(penBlenders, self.editingItr)
  422.                                 end
  423. shaderTemplate.fragment = string.format(shaderFragStr, shadeString)
  424. if penShader then
  425.       gl.DeleteShader(penShader)
  426.       penShader = nil
  427. end
  428.  
  429. penShader = gl.CreateShader(shaderTemplate)
  430.                                 Spring.Echo(self.editingItr,penShader and "shader enabled" or gl.GetShaderLog())
  431.                                
  432.                                   self._down = false
  433.   self.state = 'normal'
  434.   self:SetCaption( ("Shader blend mode: ").. tostring(self.editingItr))
  435.                         end },
  436.                 },Chili.Checkbox:New{width = "100%",
  437.                         caption='Show Pen texture',
  438.                         checked = true,
  439.                         tooltip = "Draw the pen on screen or on map",
  440.                         OnChange = { function(self, checked)
  441.                                 showPen = checked
  442.                         end },},
  443.                     Chili.Checkbox:New{width = "100%",
  444.                         caption='Project Pen from Screen to Map',
  445.                         checked = false,
  446.                         tooltip = "Toggle between map and screen projected drawing",
  447.                         OnChange = { function(self, checked)
  448.                                 projectPen = checked
  449.                         end },
  450.                 },Chili.Checkbox:New{width = "100%",
  451.                         caption='Overlay "specular" texture',
  452.                         checked = false,
  453.                         tooltip = "Overlay extra texture",
  454.                         OnChange = { function(self, checked)
  455.                                 overTex = checked
  456.                         end },
  457.                 },
  458.     colorBars,
  459.     penStepCtrl,
  460.     zoomCtrl,
  461.     texturePaintScale,texturePaintOX,texturePaintOZ,
  462.        Chili.Button:New{width = "100%",
  463.                         caption="Deselect pen",
  464.                         tooltip = "Clear Pen textures and stop drawing on map",
  465.                         OnClick = {function() penTexture = nil
  466. paintTexture = false end},
  467.                 },
  468.                    Chili.Checkbox:New{width = "100%",
  469.                         caption="Eraser pen",
  470.                         checked = false,
  471.                         tooltip = "Clear to original map texture",
  472.                         OnChange = {function(self, checked) eraser = checked;
  473.   --if eraser then paintTexture = false end
  474. end},
  475.                 },
  476.     Chili.Button:New{width = "100%",
  477.                         caption="Export to png",
  478.                         tooltip = "Save all edited squares to disk as .png images",
  479.                         OnClick = {function() exportNOW = true end},
  480.                 },
  481.   }
  482.   }
  483.   }
  484. }
  485.  
  486.        
  487.  
  488.        
  489.         mapTexSQ = gl.CreateTexture(BIG_TEX_SIZE,BIG_TEX_SIZE, {
  490.         border = false,
  491.         min_filter = GL.NEAREST,
  492.         mag_filter = GL.NEAREST,
  493.         wrap_s = GL.CLAMP_TO_EDGE,
  494.         wrap_t = GL.CLAMP_TO_EDGE,
  495. fbo = false, --????
  496.       })
  497.        
  498.         penShader = gl.CreateShader(shaderTemplate)
  499.        
  500. end
  501.  
  502.  
  503. function widget:Shutdown()
  504.     if penShader then
  505.       gl.DeleteShader(penShader)
  506.     end
  507.     if myTex then
  508.       gl.DeleteTexture(myTex)
  509.     end
  510.     for _,v in pairs(mapSpecularTextures) do
  511.       gl.DeleteTexture(v)
  512.     end
  513.    
  514.     for i,v in pairs(mapFBOtextures) do
  515.       for ii,vv in pairs(v) do
  516.         Spring.SetMapSquareTexture(i, ii, "") --should reset to the original texture
  517.         gl.DeleteTexture(vv)
  518.       end
  519.     end
  520.     if windowImageList then
  521.       windowImageList:Dispose()
  522.       windowImageList = nil
  523.     end
  524.     if windowSettingList then
  525.       windowSettingList:Dispose()
  526.       windowSettingList = nil
  527.     end
  528. end
  529.  
  530.  
  531. local function getTexTures(pointsXZ)
  532.  
  533.   if specularEditing then
  534.     if mapSpecularTextures[specularEditing]==false then
  535.       return {}
  536.     elseif mapSpecularTextures[specularEditing]==nil then --TODO do importing instead --these textures are not compressed so could be even read from map file?
  537.         --[[local OrigSpecularTexture = gl.CreateTexture(SPECULAR_TEX_SIZE,SPECULAR_TEX_SIZE, {
  538.         border = false,
  539.                     min_filter = GL.LINEAR,
  540.         mag_filter = GL.LINEAR,
  541.         wrap_s = GL.CLAMP_TO_EDGE,
  542.         wrap_t = GL.CLAMP_TO_EDGE,
  543. fbo = false,
  544.       })
  545.  
  546.         if not Spring.GetMapSquareTexture(-1, -1, 0, OrigSpecularTexture) then
  547.           mapSpecularTexture = false
  548.           glDeleteTexture(OrigSpecularTexture)
  549.           Spring.Echo("ERROR: Getting Specular Texture FAILED")
  550.           return {}
  551.         end
  552.         --]]
  553.       mapSpecularTextures[specularEditing] = gl.CreateTexture(SPECULAR_TEX_SIZE,SPECULAR_TEX_SIZE, {
  554.         border = false,
  555.                     min_filter = GL.LINEAR,
  556.         mag_filter = GL.LINEAR,
  557.         wrap_s = GL.CLAMP_TO_EDGE,
  558.         wrap_t = GL.CLAMP_TO_EDGE,
  559. fbo = true,
  560.       })
  561.  
  562.  
  563.         gl.RenderToTexture(mapSpecularTextures[specularEditing],
  564.         function()
  565.         gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,0.5)
  566.     --gl.Texture(OrigSpecularTexture)
  567.     --gl.TexRect(-1,-1, 1, 1,0, 0, 1, 1)
  568. end)
  569. --  glDeleteTexture(OrigSpecularTexture)
  570.  local set = "set failed!!!"
  571.         if mapSpecularTextures[specularEditing] and Spring.SetMapSquareTexture(specularEditing,specularEditing,mapSpecularTextures[specularEditing]) then set = nil end
  572.         Spring.Echo("Created Specular mapTexture ID: ", tostring(mapSpecularTextures[specularEditing]), set)
  573.     end
  574.    
  575.     return {[pointsXZ[1]]={[pointsXZ[2]]=mapSpecularTextures[specularEditing]}} --RETURN specular
  576.    
  577.   end
  578.  
  579.   local minX,minZ = math.huge, math.huge
  580.   local maxX,maxZ = 0, 0
  581.  
  582.   for i=1,#pointsXZ,2 do
  583.     --Spring.Echo(pointsXZ[i],pointsXZ[i+1])
  584.     if pointsXZ[i] < minX then minX = pointsXZ[i] end
  585.     if pointsXZ[i] > maxX then maxX = pointsXZ[i] end
  586.     if pointsXZ[i+1] < minZ then minZ = pointsXZ[i+1] end
  587.     if pointsXZ[i+1] > maxZ then maxZ = pointsXZ[i+1] end
  588.   end
  589.   minX,minZ = max(0,floor(minX/BIG_TEX_SIZE)),max(0,floor(minZ/BIG_TEX_SIZE))
  590.   maxX,maxZ = min(TEXS_X,floor(maxX/BIG_TEX_SIZE)),min(TEXS_X,floor(maxZ/BIG_TEX_SIZE))
  591.  
  592.   local squares = {}
  593.  
  594.   for ix=minX,maxX,1 do
  595.     for iz=minZ,maxZ,1 do
  596.       squares[#squares+1] = {ix,iz}
  597.     end
  598.   end
  599.  
  600.   local retMap = {} --[offsetX][offsetZ] = texID
  601.  
  602.   for _,v in ipairs(squares) do
  603.    
  604.     local sqTex = mapFBOtextures[v[1]] and mapFBOtextures[v[1]][v[2]]
  605.     if not sqTex then
  606.       if not mapFBOtextures[v[1]] then mapFBOtextures[v[1]] = {} end
  607.              sqTex = gl.CreateTexture(BIG_TEX_SIZE,BIG_TEX_SIZE, {
  608.         border = false,
  609.         --min_filter = GL.NEAREST,
  610.         --mag_filter = GL.NEAREST,
  611.                     min_filter = GL.LINEAR,
  612.         mag_filter = GL.LINEAR,
  613.         --target     =  GL_TEXTURE_2D
  614.         --wrap_s = GL.CLAMP,
  615.         --wrap_t = GL.CLAMP,
  616.         wrap_s = GL.CLAMP_TO_EDGE,
  617.         wrap_t = GL.CLAMP_TO_EDGE,
  618. fbo = true,
  619.       })
  620.         Spring.GetMapSquareTexture(v[1], v[2], 0, mapTexSQ)
  621.         gl.RenderToTexture(sqTex,
  622.         function()
  623.     --gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,1)
  624.     gl.Texture(mapTexSQ)
  625.     gl.TexRect(-1,-1, 1, 1,0, 0, 1, 1)
  626. end)
  627.         mapFBOtextures[v[1]][v[2]] = sqTex
  628.        
  629.         local set = "set failed"
  630.         if sqTex and Spring.SetMapSquareTexture(v[1],v[2],sqTex) then set = "set ok" end
  631.         Spring.Echo("Created mapTexture", v[1],v[2],"ID: ", tostring(sqTex), set)
  632.              end
  633.              if sqTex then
  634.                if not retMap[pointsXZ[1]-v[1]*BIG_TEX_SIZE] then retMap[pointsXZ[1]-v[1]*BIG_TEX_SIZE] = {} end
  635.                if not modifiedFBOtextures[v[1]] then modifiedFBOtextures[v[1]] = {} end
  636.                retMap[pointsXZ[1]-v[1]*BIG_TEX_SIZE][pointsXZ[2]-v[2]*BIG_TEX_SIZE] = sqTex
  637.                modifiedFBOtextures[v[1]][v[2]] = modifiedFBOtextures[v[1]][v[2]] and modifiedFBOtextures[v[1]][v[2]]+1 or 1
  638.              end
  639.              end
  640.  
  641.              return retMap
  642. end
  643.  
  644. local function export2png(exportNOW)
  645.   local dir = mainDir..Game.mapName
  646.   Spring.CreateDir(dir)
  647.   local startx,startz = 0,0
  648.   if type(exportNOW)=="table" then -- don't halt
  649.     startx,startz = exportNOW[1], exportNOW[2]
  650.   end
  651.   for x=startx,TEXS_X-1,1 do
  652.     for z=startz,TEXS_Z-1,1 do
  653.       local tex = mapFBOtextures[x] and mapFBOtextures[x][z]
  654.       if tex and modifiedFBOtextures[x] and modifiedFBOtextures[x][z] then
  655.         local fn = dir.."/"..x.."_"..z.."__".. os.date("%Y%m%d%H") .. string.format("%06d",modifiedFBOtextures[x][z]) ..".png"
  656.         if VFS.FileExists(fn) then --check if no further modifications --every hour a new save even if no modif.
  657.           Spring.Echo("Not saving an already existing modified square",x,z,modifiedFBOtextures[x][z])
  658.       else
  659.         Spring.Echo("Saving a modified square to '"..fn.."'")
  660.   gl.RenderToTexture(tex,gl.SaveImage,0,0,BIG_TEX_SIZE,BIG_TEX_SIZE,fn)
  661.   exportNOW = {x,z+1}
  662.   return exportNOW
  663.       end
  664.       else
  665.       local fn = dir.."/"..x.."_"..z.."__0.png"
  666.       if VFS.FileExists(fn) then --check if the original texture already exists
  667.         Spring.Echo("Not saving already existing unmodified square",x,z)
  668.       else
  669.         Spring.Echo("Saving an unmodified square to '"..fn.."'")
  670.         if not Spring.GetMapSquareTexture(x, z, 0, mapTexSQ) then
  671.           Spring.Echo("ERROR getting the texture",x,z,"(maybe rezoom and try again later?)")
  672.       else
  673.                 if not myTex then            myTex = gl.CreateTexture(BIG_TEX_SIZE,BIG_TEX_SIZE, { --can often fail when saving but no worries it is only the unmodified textures
  674.         border = false,
  675.         --min_filter = GL.NEAREST,
  676.         --mag_filter = GL.NEAREST,
  677.                     min_filter = GL.LINEAR,
  678.         mag_filter = GL.LINEAR,
  679.         --target     =  GL_TEXTURE_2D
  680.         --wrap_s = GL.CLAMP,
  681.         --wrap_t = GL.CLAMP,
  682.                 wrap_s = GL.CLAMP_TO_EDGE,
  683.         wrap_t = GL.CLAMP_TO_EDGE,
  684. fbo = true,
  685.       })end
  686.         if myTex then
  687.                 gl.RenderToTexture(myTex,
  688.         function()
  689.     gl.Texture(mapTexSQ)
  690.     gl.TexRect(-1,-1, 1, 1,0, 0, 1, 1)
  691. end)
  692.         gl.RenderToTexture(myTex,gl.SaveImage,0,0,BIG_TEX_SIZE,BIG_TEX_SIZE,fn)
  693.         exportNOW = {x,z+1}
  694.         return exportNOW
  695.                 else Spring.Echo("warning ",x, z,"couldn't be saved")
  696.         end
  697.     end
  698.       end
  699.     end
  700.   end
  701.   startz = 0
  702. end
  703.  
  704. for k,v in pairs(mapSpecularTextures) do
  705.   local fn
  706.   for kk,vv in pairs(editingLayers) do
  707.     if k==vv then
  708.       fn = tostring(kk)
  709.       break
  710.     end
  711.   end
  712.   fn = (dir.."/".. (fn or "wut").. os.date("%Y%m%d%H%S") .. ".png")
  713.   Spring.Echo("Saving ".. tostring(fn) )
  714.   gl.RenderToTexture(v,gl.SaveImage,0,0,SPECULAR_TEX_SIZE,SPECULAR_TEX_SIZE,fn)
  715. end
  716.  
  717. exportNOW = false
  718. return exportNOW
  719. end
  720.  
  721. local function drawPen(pointsXZ, textureMap, penTexture)
  722.   local rT
  723.  
  724.   local texSizeX = specularEditing and Game.mapSizeX or BIG_TEX_SIZE
  725.   local texSizeY = specularEditing and Game.mapSizeZ or BIG_TEX_SIZE
  726.  
  727.   local color = colorBars.color --{1,1,1,1}
  728.  
  729.  
  730.   gl.Texture(1, penTexture)
  731.   gl.Texture(2, paintTexture)
  732.   ptX,ptZ = 0.5/texturePaintZoom,0.5/texturePaintZoom
  733.        
  734. if penShader then gl.UseShader(penShader) end
  735.        
  736.   for x,v in pairs(textureMap) do
  737.     for z,tex in pairs(v) do
  738.       --Spring.Echo("Painting pen at ", x,z,pointsXZ[1],pointsXZ[2],(x+pointsXZ[1])/BIG_TEX_SIZE,"ID: ", tostring(tex))
  739.       --Spring.Echo("Painting pen at ",(x)/BIG_TEX_SIZE, (z)/BIG_TEX_SIZE,"ID: ", tostring(tex))
  740.       --gl.Texture(0, tex)
  741.       if eraser then
  742.         if not Spring.GetMapSquareTexture(x, z, 0, mapTexSQ) then Spring.Echo("Error getting the original texture") end --BUG GED
  743.         gl.Texture(2, mapTexSQ)
  744.         ptX,ptZ = 0.5,0.5
  745.       end
  746. gl.Texture(0, tex)
  747.       gl.RenderToTexture(tex,
  748.         function()
  749.         --gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,1)
  750.     --gl.Texture(penTexture)
  751.         --gl.Texture(0, penTexture)
  752.         --gl.Texture(2, penTexture)
  753.     --gl.TexRect((x)/BIG_TEX_SIZE*2-1,(z)/BIG_TEX_SIZE*2-1, (x+pointsXZ[5]-pointsXZ[1])/BIG_TEX_SIZE*2-1,(z+pointsXZ[6]-pointsXZ[2])/BIG_TEX_SIZE*2-1,   0, 0, 1, 1)
  754.     local pp = {x+pointsXZ[1],z+pointsXZ[2], x+pointsXZ[3],z+pointsXZ[4],x+pointsXZ[7],z+pointsXZ[8],x+pointsXZ[5],z+pointsXZ[6]}
  755.     local fx,fz = pointsXZ[1],pointsXZ[2]
  756.     for i=1,#pp,2 do
  757.       pp[i] = (pp[i]-fx)/texSizeX*2-1
  758.       pp[i+1] = (pp[i+1]-fz)/texSizeY*2-1
  759.     end
  760.  
  761.         gl.BeginEnd(GL.POLYGON --GL.QUADS
  762.           ,function()
  763.        
  764.     gl.Color(color)
  765.         gl.MultiTexCoord(1, 0,0)  
  766.     gl.MultiTexCoord(0, (pp[1]+1)/2,(pp[2]+1)/2)
  767.     gl.MultiTexCoord(2, (pp[1]+1)*ptX+texturePaintOffsetX,(pp[2]+1)*ptZ+texturePaintOffsetZ)
  768.     gl.Vertex(pp[1], pp[2])
  769.    
  770. gl.MultiTexCoord(1, 0,1)  
  771.     gl.MultiTexCoord(0, (pp[3]+1)/2,(pp[4]+1)/2)
  772.     gl.MultiTexCoord(2, (pp[3]+1)*ptX+texturePaintOffsetX,(pp[4]+1)*ptZ+texturePaintOffsetZ)
  773.     gl.Vertex(pp[3], pp[4])
  774.    
  775.    gl.MultiTexCoord(1, 1,1)  
  776.    gl.MultiTexCoord(0, (pp[7]+1)/2,(pp[8]+1)/2)
  777.    gl.MultiTexCoord(2, (pp[7]+1)*ptX+texturePaintOffsetX,(pp[8]+1)*ptZ+texturePaintOffsetZ)
  778.     gl.Vertex(pp[7], pp[8])
  779.    
  780.  gl.MultiTexCoord(1, 1,0)  
  781.  gl.MultiTexCoord(0, (pp[5]+1)/2,(pp[6]+1)/2)
  782.  gl.MultiTexCoord(2, (pp[5]+1)*ptX+texturePaintOffsetX,(pp[6]+1)*ptZ+texturePaintOffsetZ)
  783.     gl.Vertex(pp[5], pp[6])
  784.    
  785.     end
  786.     )
  787.     end)
  788. rT = tex
  789.   end
  790. end
  791.  
  792. gl.UseShader(0)
  793.  
  794. return rT
  795. end
  796.  
  797.  
  798. local buttonPressed = false
  799.  
  800. local tx
  801.  
  802. local previousDrawMY, previousDrawMX, previousTime = 0,0,0
  803. local mapPoints = {0,0,0,0,0,0,0,0}
  804.  
  805. function widget:DrawWorld()
  806.   gl.DepthTest(false)
  807.         if (not projectPen) and (not buttonPressed) and penTexture and type(penTexture)=="string" then
  808.           if showPen then
  809.           local color = colorBars.color
  810.  
  811.   local ptX,ptZ = 1024*texturePaintZoom    ,1024*texturePaintZoom    
  812.  
  813.                       gl.Texture(0,penTexture)
  814.       gl.Texture(1,paintTexture)
  815.               gl.BeginEnd(GL.POLYGON --GL.QUADS
  816.           ,function()
  817.        
  818.     gl.Color(color)
  819.         gl.MultiTexCoord(0, 0,0)  
  820.     gl.MultiTexCoord(1, mapPoints[1]/ptX+texturePaintOffsetX,mapPoints[2]/ptZ+texturePaintOffsetZ)
  821.     gl.Vertex(mapPoints[1],Spring.GetGroundHeight(mapPoints[1],mapPoints[2]), mapPoints[2])
  822.    
  823. gl.MultiTexCoord(0, 0,1)  
  824.     gl.MultiTexCoord(1, mapPoints[3]/ptX+texturePaintOffsetX,mapPoints[4]/ptZ+texturePaintOffsetZ)
  825.     gl.Vertex(mapPoints[3],Spring.GetGroundHeight(mapPoints[3],mapPoints[4]), mapPoints[4])
  826.    
  827.    gl.MultiTexCoord(0, 1,1)  
  828.    gl.MultiTexCoord(1, mapPoints[5]/ptX+texturePaintOffsetX,mapPoints[6]/ptZ+texturePaintOffsetZ)
  829.     gl.Vertex(mapPoints[5],Spring.GetGroundHeight(mapPoints[5],mapPoints[6]), mapPoints[6])
  830.    
  831.  gl.MultiTexCoord(0, 1,0)
  832.  gl.MultiTexCoord(1, mapPoints[7]/ptX+texturePaintOffsetX,mapPoints[8]/ptZ+texturePaintOffsetZ)
  833.     gl.Vertex(mapPoints[7],Spring.GetGroundHeight(mapPoints[7],mapPoints[8]), mapPoints[8])
  834.    
  835.     end
  836.     )
  837.           gl.Texture(0,false)
  838.       gl.Texture(1,false)
  839.         end
  840. gl.Color(1,1,1,1)
  841. if overTex and specularEditing and mapSpecularTextures[specularEditing] then
  842.   gl.Texture(mapSpecularTextures[specularEditing])
  843.   gl.DrawGroundQuad(0,0,Game.mapSizeX,Game.mapSizeZ,false,true)
  844. end
  845.  
  846. gl.Texture(false)
  847. gl.DepthTest(true)
  848.         end
  849. end
  850. local lm,mm,rm
  851. function widget:MousePress(x, y, button)
  852.     if penTexture and button == 1 then
  853.       lm = true
  854.       return true
  855. end
  856.   return false
  857. end
  858.  
  859. function widget:MouseRelease(x, y, button)
  860.       if button == 1 then
  861.           lm = false
  862.         end
  863. end
  864.  
  865. function widget:MouseMove(x, y, dx, dy, button)
  866.  
  867. end
  868.  
  869. function widget:DrawScreen()
  870.  
  871.  
  872.    gl.Color(1,1,1,1)
  873.    
  874.    if exportNOW then exportNOW = export2png(exportNOW) end
  875. --[[ gl.Texture(myTex)
  876.  
  877. local ss = gl.TextureInfo(myTex)
  878.  --gl.Billboard()
  879.  gl.TexRect(50,60, 50 + ss.xsize,60+ss.ysize)
  880.  
  881.  gl.Texture(false)
  882.  --]]
  883.   if penTexture and type(penTexture)=="string" then
  884.    
  885.    gl.Color(1,1,1,1)
  886.  gl.Texture(penTexture)--needed for caching the texture info..
  887. --local mxo,myo, lm,mm,rm = Spring.GetMouseState()
  888. local mxo,myo = Spring.GetMouseState()
  889. local ss = gl.TextureInfo(penTexture)
  890. local mx,my = mxo,myo
  891. if projectPen then
  892.   mx,my = math.floor(mxo-ss.xsize/2*penZoom), math.floor(myo-ss.ysize/2*penZoom)
  893. end
  894. mapPoints = {mx,my, mx,my+ss.ysize*penZoom, mx+ss.xsize*penZoom,my+ss.ysize*penZoom, mx+ss.xsize*penZoom,my}
  895. for i=1,#mapPoints,2 do
  896.   if (not projectPen) and i ~= 1 then
  897.     mapPoints[1] = mapPoints[1]-ss.xsize*penZoom*0.5
  898.     mapPoints[2] = mapPoints[2]+ss.ysize*penZoom*0.5
  899.     mapPoints[3] = mapPoints[1]
  900.     mapPoints[4] = mapPoints[2]-ss.ysize*penZoom
  901.         mapPoints[5] = mapPoints[1]+ss.xsize*penZoom
  902.     mapPoints[6] = mapPoints[2]-ss.ysize*penZoom
  903.         mapPoints[7] = mapPoints[1]+ss.xsize*penZoom
  904.     mapPoints[8] = mapPoints[2]
  905.     break
  906.   else
  907.     local _,xyz = Spring.TraceScreenRay(mapPoints[i],mapPoints[i+1], true,false,true)
  908.     if xyz then
  909.       mapPoints[i] = xyz[1]
  910.       mapPoints[i+1] = xyz[3]
  911.     end
  912.   end
  913. end
  914.  
  915.  --gl.Billboard()
  916.  
  917.  --REM
  918.  --[[
  919.  if tx then --show the last edited texture in screenspace
  920. gl.Texture(tx)
  921. local ss = gl.TextureInfo(tx)
  922.  --gl.Billboard()
  923.  gl.TexRect(50,60, 50 + ss.xsize,60+ss.ysize)
  924.  gl.Texture(false)
  925.  end--]]
  926.  --REMOVE
  927.  
  928.  --REMOVE
  929.  --[[
  930.     gl.RenderToTexture(myTex,
  931.         function()
  932.     gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,1)
  933.     gl.TexRect(-1,-1, 1, 1,0, 0, 1, 1)
  934. end)--]]
  935.  --REMOVE
  936. gl.Texture(false)
  937.  
  938. if floor(previousDrawMY/penStep) ~= floor(myo/penStep) or floor(previousDrawMX/penStep) ~= floor(mxo/penStep) or previousTime+penTimeStep < widgetHandler:GetHourTimer() then
  939.   buttonPressed = false
  940.   previousDrawMY = myo
  941.   previousDrawMX = mxo
  942.   previousTime = widgetHandler:GetHourTimer()
  943. end
  944.  
  945.  if lm and not buttonPressed then
  946.    --Spring.Echo("drawingPen at",mapPoints[1],mapPoints[2])
  947.    buttonPressed = true
  948.    local tmap = getTexTures(mapPoints)
  949.  tx = drawPen(mapPoints, tmap, penTexture)
  950.  
  951.   else
  952.     if not lm then
  953.    buttonPressed = false
  954.     end
  955.     if projectPen and not buttonPressed and showPen then
  956.       gl.Texture(0,penTexture)
  957.       gl.Texture(1,paintTexture)
  958.       gl.TexRect(mx,my, mx+ss.xsize*penZoom,my+ss.ysize*penZoom) --hides
  959.       gl.Texture(0,false)
  960.       gl.Texture(1,false)
  961.     end
  962.  end
  963.  gl.Texture(false)
  964. end
  965.  
  966.  
  967.  
  968. end
  969.  
  970.  
  971. --------------------------------------------------------------------------------
  972. --------------------------------------------------------------------------------