SHARE
TWEET

Untitled

a guest Feb 23rd, 2017 106 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //#CLIENTSIDE
  2. const SHIFT          = 256;
  3. const CTRL           = 512;
  4. const ALT            = 1024;
  5. const DEFAULT_WIDTH  = 400;
  6. const DEFAULT_HEIGHT = 330;
  7. const DEFAULT_ITEM   = "bed.png";
  8. const DEFAULT_KEY    = SHIFT + VK_T;
  9. const DEFAULT_BGIMG  = "dusty_setshapebg0.png";
  10.  
  11. function GraalControl.onKeyDown(temp.code) {
  12.   if (temp.code == DEFAULT_KEY) {
  13.     if (isObject("DustyShapeGen_Window")) {
  14.       if (DustyShapeGen_Window.visible) DustyShapeGen_Window.hide();
  15.       else DustyShapeGen_Window.show();
  16.     } else createWindow();
  17.   }
  18. }
  19.  
  20. function DustyShapeGen_Window.onKeyDown(temp.code) {
  21.   if (temp.code == DEFAULT_KEY) {
  22.     if (isObject("DustyShapeGen_Window")) {
  23.       if (DustyShapeGen_Window.visible) DustyShapeGen_Window.hide();
  24.       else DustyShapeGen_Window.show();
  25.     } else createWindow();
  26.   }
  27. }
  28.  
  29. function onCreated() {
  30.   // Decode string of BGTILE back into PNG format and save image so no external images are needed
  31.   temp.bgtile = base64decode(BGTILE);
  32.   temp.bgtile.savestring(DEFAULT_BGIMG,0);
  33.  
  34.   // List all the tile types, a color association and a tooltip description
  35.   this.tileTypes = {
  36.     {0},{1}, // 0 - 1 are not valid tile types, don't define
  37.     {2 ,{194,35 ,35 },"Hurt Underground"},
  38.     {3 ,{156,107,66 },"Chair"},
  39.     {4 ,{189,189,255},"Bed Upper"},
  40.     {5 ,{223,223,255},"Bed Lower"},
  41.     {6 ,{41 ,123,57 },"Swamp"},
  42.     {7 ,{99 ,0  ,0  },"Lava Swamp"},
  43.     {8 ,{90 ,132,198},"Shallow Water"},
  44.     {9},{10}, // 9 - 10 are not valid tile types, don't define
  45.     {11,{57 ,99 ,165},"Water"},
  46.     {12,{255,0  ,0  },"Lava"},
  47.     {13},{14},{15},{16},{17},{18},{19},
  48.     {20,{99 ,82 ,49 },"Throw-through"},
  49.     {21,{123,189,148},"Jumping"},
  50.     {22,{49 ,49 ,49 },"Blocking"},
  51.   };
  52.  
  53.   // Destroy existing windows
  54.   if (isObject("DustyShapeGen_Window")) DustyShapeGen_Window.destroy();
  55.   if (isObject("DustyShapeGen_OutputWindow")) DustyShapeGen_OutputWindow.destroy();
  56. }
  57.  
  58. function createWindow() {
  59.   // Destroy existing windows
  60.   if (isObject("DustyShapeGen_Window")) DustyShapeGen_Window.destroy();
  61.   if (isObject("DustyShapeGen_OutputWindow")) DustyShapeGen_OutputWindow.destroy();
  62.  
  63.   // Create a 64x64 empty array for mapping inputs to
  64.   this.tilemap = new[64*64];
  65.  
  66.   // Create a window
  67.   new GuiWindowCtrl("DustyShapeGen_Window") {
  68.     profile = GuiBlueWindowProfile;
  69.  
  70.     // No control transparency support in external windows = no use
  71.     //style = $pref::video::defaultguistyle;
  72.     //isexternal = true;
  73.     //showOnTaskBar = true;
  74.     clientrelative = true;
  75.     width = DEFAULT_WIDTH;
  76.     height = DEFAULT_HEIGHT;
  77.     x = (screenwidth - width)/2;
  78.     y = (screenheight - height)/2;
  79.     text = "Setshape Editor";
  80.  
  81.     // A button to generate the code
  82.     new GuiButtonCtrl("DustyShapeGen_Button_Generate") {
  83.       profile = GuiBlueButtonProfile;
  84.       x = 2;
  85.       y = 2;
  86.       width = 64;
  87.       height = 24;
  88.       text = "Generate";
  89.     }
  90.  
  91.     // A button to clear the tile map
  92.     new GuiButtonCtrl("DustyShapeGen_Button_Clear") {
  93.       profile = GuiBlueButtonProfile;
  94.       width = 64;
  95.       height = 24;
  96.       x = DustyShapeGen_Window.clientwidth - width - 2;
  97.       y = 2;
  98.       text = "Clear";
  99.       horizsizing = "left";
  100.     }
  101.  
  102.     // A text control to input the background image
  103.     new GuiTextEditCtrl("DustyShapeGen_Edit_Image") {
  104.       profile = GuiBlueTextEditProfile;
  105.       x = DustyShapeGen_Button_Generate.x + DustyShapeGen_Button_Generate.width + 2;
  106.       y = 3;
  107.       width = DustyShapeGen_Window.width - x - 19 - DustyShapeGen_Button_Clear.width + 2;
  108.       height = 22;
  109.       text = DEFAULT_ITEM;
  110.       horizsizing = "width";
  111.     }
  112.  
  113.     // A control to host the tile type swatches
  114.     new GuiControl("DustyShapeGen_Picker_Control") {
  115.       useownprofile = true;
  116.       profile.border = 0;
  117.       profile.fillcolor = {0,0,0,50};
  118.       profile.opaque = true;
  119.       x = 0;
  120.       y = DustyShapeGen_Button_Generate.y + DustyShapeGen_Button_Generate.height + 2;
  121.       width = 24;
  122.       height = thiso.tileTypes.size()*22+4;
  123.       vertsizing = "height";
  124.     }
  125.  
  126.     // Main control to host the canvas
  127.     new GuiBitmapCtrl("DustyShapeGen_Main") {
  128.       x = DustyShapeGen_Picker_Control.x + DustyShapeGen_Picker_Control.width;
  129.       y = DustyShapeGen_Picker_Control.y;
  130.       width = DustyShapeGen_Window.width - x - 16;
  131.       height = DustyShapeGen_Window.height - y - 37;
  132.       bitmap = DEFAULT_BGIMG;
  133.       wrap = true;
  134.       horizsizing = "width";
  135.       vertsizing = "height";
  136.  
  137.       // Background control
  138.       new GuiShowImgCtrl("DustyShapeGen_Main_Image") {
  139.         useownprofile = true;
  140.         profile.modal = false;
  141.         width = DustyShapeGen_Main.width;
  142.         height = DustyShapeGen_Main.height;
  143.         image = "block.png";
  144.         x = y = 0;
  145.         //horizsizing = "width";
  146.         //vertsizing = "height";
  147.         cliptobounds = false;
  148.         clipchildren = false;
  149.       }
  150.  
  151.       // A tiled background image
  152.       new GuiBitmapCtrl("DustyShapeGen_MainOverlay") {
  153.         x = y = 0;
  154.         width = DustyShapeGen_Main_Image.width;
  155.         height = DustyShapeGen_Main_Image.height;
  156.         bitmap = "dc_bg_transgrid0.png";
  157.         wrap = true;
  158.         horizsizing = "width";
  159.         vertsizing = "height";
  160.         useownprofile = true;
  161.         profile.opaque = true;
  162.         profile.modal = false;
  163.         profile.transparency = .33;
  164.       }
  165.  
  166.       // A control to capture mouse input and change tile map
  167.       new GuiControl("DustyShapeGen_MainTileMapControl") {
  168.         useownprofile = true;
  169.         profile.border = 0;
  170.         profile.fillcolor = {0,0,0,0};
  171.         profile.opaque = true;
  172.         mode = 1;
  173.         alpha = .75;
  174.         x = y = 0;
  175.         width = DustyShapeGen_Main_Image.width;
  176.         height = DustyShapeGen_Main_Image.height;
  177.         horizsizing = "width";
  178.         vertsizing = "height";
  179.  
  180.         thiso.catchevent(this,"onMouseDown","onChangeTileMap");
  181.         thiso.catchevent(this,"onRightMouseDown","onEraseTileMap");
  182.         thiso.catchevent(this,"onRightMouseDragged","onEraseTileMap");
  183.         thiso.catchevent(this,"onMouseDragged","onChangeTileMap");
  184.       }
  185.     }
  186.   }
  187.   // Add swatch controls
  188.   addTypeControls();
  189.   // Set selected tile type swatch to 22
  190.   selectType(22);
  191.   // Set first loaded image
  192.   onUpdateImage(DEFAULT_ITEM);
  193.   // Update the tile map control
  194.   onUpdateTileMap();
  195.   // Make it the first responder when opened
  196.   DustyShapeGen_Window.makefirstResponder(true);
  197. }
  198.  
  199. // Capture input from text control to change the background image
  200. function DustyShapeGen_Edit_Image.onAction() {
  201.   temp.img = DustyShapeGen_Edit_Image.text;
  202.   onUpdateImage(temp.img);
  203. }
  204.  
  205. // Clear the tile map array and update the control
  206. function DustyShapeGen_Button_Clear.onAction() {
  207.   this.tilemap = new[64*64];
  208.   onUpdateTileMap();
  209. }
  210.  
  211. // Generate setshape2() code
  212. function DustyShapeGen_Button_Generate.onAction() {
  213.   // Find the maximum width and height of the array and trim it down
  214.   temp.maxw = temp.maxh = 0;
  215.   for (temp.i=0;temp.i<this.tilemap.size();temp.i++) {
  216.     temp.x = temp.i%64;
  217.     temp.y = int(temp.i/64);
  218.     temp.t = this.tilemap[temp.i];
  219.  
  220.     if (temp.t > 0) {
  221.       if (temp.x > temp.maxw) temp.maxw = temp.x;
  222.       if (temp.y > temp.maxh) temp.maxh = temp.y;
  223.     }
  224.   }
  225.  
  226.   temp.maxw++;
  227.   temp.maxh++;
  228.   for (temp.i=0;temp.i<temp.maxw*temp.maxh;temp.i++) {
  229.     temp.x = temp.i%temp.maxw;
  230.     temp.y = int(temp.i/temp.maxw)*64;
  231.     temp.t = this.tilemap[temp.x+temp.y];
  232.     temp.tiles.add(temp.t);
  233.   }
  234.  
  235.   // Output the code to a new window
  236.   RenderOutput(temp.tiles,temp.maxw,temp.maxh);
  237. }
  238.  
  239. function RenderOutput(arr,w,h) {
  240.   // Destroy old object
  241.   if (isObject("DustyShapeGen_OutputWindow")) DustyShapeGen_OutputWindow.destroy();
  242.  
  243.   new GuiWindowCtrl("DustyShapeGen_OutputWindow") {
  244.     profile = GuiBlueWindowProfile;
  245.     width = DustyShapeGen_Window.width;
  246.     height = DustyShapeGen_Window.height;
  247.     x = DustyShapeGen_Window.x;
  248.     y = DustyShapeGen_Window.y;
  249.     text = "SetShape2 Output";
  250.     clientrelative = true;
  251.    
  252.     new GuiScrollCtrl("DustyShapeGen_OutputScroll") {
  253.       profile = GuiBlueScrollProfile;
  254.       x = 4;
  255.       y = 4;
  256.       width = DustyShapeGen_OutputWindow.clientwidth - x*2;
  257.       height = DustyShapeGen_OutputWindow.clientheight - y*2 - 26;
  258.       hScrollBar = "dynamic";
  259.       vScrollBar = "dynamic";
  260.       horizsizing = "width";
  261.       vertsizing = "height";
  262.  
  263.       new GuiMLTextCtrl("DustyShapeGen_OutputText") {
  264.         profile = GuiBlueMLTextProfile;
  265.         useownprofile = true;
  266.         profile.fonttype = "courier new";
  267.         profile.fontcolor = {255,255,255,255};
  268.         x = 5;
  269.         y = 2;
  270.         width = DustyShapeGen_OutputScroll.width - (DustyShapeGen_OutputScroll.x*4);
  271.         height = DustyShapeGen_OutputScroll.height;
  272.         wordwrap = false;
  273.         text = "";
  274.       }
  275.     }
  276.  
  277.     new GuiTextEditSliderCtrl("DustyShapeGen_OutputIndent") {
  278.       profile = GuiBlueTextEditSliderProfile;
  279.       x = DustyShapeGen_OutputScroll.x;
  280.       y = DustyShapeGen_OutputScroll.y + DustyShapeGen_OutputScroll.height + 5;
  281.       width = 80;
  282.       height = 20;
  283.       format = "Indent: %d";
  284.       range = {0,20};
  285.       value = 1;
  286.       vertsizing = "top";
  287.     }
  288.  
  289.     new GuiButtonCtrl("DustyShapeGen_OutputButton_Close") {
  290.       profile = GuiBlueButtonProfile;
  291.       width = 80;
  292.       height = 20;
  293.       x = DustyShapeGen_OutputScroll.width - width;
  294.       y = DustyShapeGen_OutputIndent.y;
  295.       text = "Close";
  296.       vertsizing = "top";
  297.     }
  298.  
  299.     new GuiCheckBoxCtrl("DustyShapeGen_OutputCheckbox") {
  300.       profile = GuiBlueCheckBoxProfile;
  301.       useownprofile = true;
  302.       profile.fontcolor = {25,25,125,255};
  303.       profile.textshadow = true;
  304.       profile.shadowcolor = {255,255,255,255};
  305.       x = DustyShapeGen_OutputIndent.x + DustyShapeGen_OutputIndent.width + 10;
  306.       y = DustyShapeGen_OutputIndent.y;
  307.       width = 100;
  308.       height = 20;
  309.       text = " GS1";
  310.       vertsizing = "top";
  311.     }
  312.   }
  313.  
  314.   DustyShapeGen_OutputIndent.value = 1;
  315.   DustyShapeGen_OutputCheckbox.checked = 0;
  316.   // Create a template for indent spacing. Derive indents from this
  317.   temp.emptyspace = "                                          ";
  318.  
  319.   temp.output = new[int(arr.size()/w)+2];
  320.   temp.indent = emptyspace.substring(0,DustyShapeGen_OutputIndent.value*2);
  321.   output[0] = indent @ "setshape2(" @ w @ "," @ h @ ",{";
  322.   for (temp.i=0;i<arr.size();i++) {
  323.     // Createa a new line when array value exceeds width of selection
  324.     if (i%w == 0) output[int(i/w)+1] = indent @ "  " @ arr[i] @ (arr[i].length() == 1 ? " " : "") @ ",";
  325.     // Otherwise append rest of array
  326.     else output[int(i/w)+1] @= arr[i] @ (arr[i].length() == 1 ? " " : "") @ ",";
  327.   }
  328.   output[int(arr.size()/w)+1] = indent @ "});";
  329.   DustyShapeGen_OutputText.text = "";
  330.   DustyShapeGen_OutputText.setlines(output);
  331. }
  332.  
  333. // Close button functionality
  334. function DustyShapeGen_OutputButton_Close.onAction() {
  335.   DustyShapeGen_OutputWindow.destroy();
  336. }
  337.  
  338. // Toggle GS1/GS2 output
  339. function DustyShapeGen_OutputCheckbox.onAction() {
  340.   // Replace GS2 with GS1 script
  341.   if (DustyShapeGen_OutputCheckbox.checked) {
  342.     DustyShapeGen_OutputText.text = shared.replacetext(DustyShapeGen_OutputText.text,"setshape2(","setshape2 ");
  343.     DustyShapeGen_OutputText.text = shared.replacetext(DustyShapeGen_OutputText.text,"});","};");
  344.   // Replace GS1 with GS2 script
  345.   } else {
  346.     DustyShapeGen_OutputText.text = shared.replacetext(DustyShapeGen_OutputText.text,"setshape2 ","setshape2(");
  347.     DustyShapeGen_OutputText.text = shared.replacetext(DustyShapeGen_OutputText.text,"};","});");
  348.   }
  349. }
  350.  
  351. function DustyShapeGen_OutputIndent.onMouseDown() {
  352.   while (leftmousebuttonglobal) {
  353.     // Loop through all lines and re-indent
  354.     temp.emptyspace = "                                          ";
  355.     temp.indent = emptyspace.substring(0,DustyShapeGen_OutputIndent.value*2);
  356.     temp.output = DustyShapeGen_OutputText.getlines();
  357.     for (temp.i=0;i<output.size();i++) {
  358.       // Get rid of pre-existing newlines so they don't stack with new ones
  359.       output[i] = shared.replacetext(output[i],"\n","");
  360.       // Trim old indents
  361.       output[i] = output[i].trim();
  362.       // Add new indents
  363.       output[i] = (i in |1,output.size()-2| ? "  " : "") @ indent @ output[i];
  364.     }
  365.     DustyShapeGen_OutputText.text = "";
  366.     DustyShapeGen_OutputText.setlines(output);
  367.     sleep(0.05);
  368.   }
  369. }  
  370.  
  371. // Eraser tool, replace tile at mouse position with tiletype 0
  372. function onEraseTileMap(temp.obj,temp.mod,temp.mx,temp.my) {
  373.   temp.local = temp.obj.globaltolocalcoord({temp.mx,temp.my});
  374.   temp.mx = temp.local[0];
  375.   temp.my = temp.local[1];
  376.  
  377.   temp.x = int(temp.mx/16);
  378.   temp.y = int(temp.my/16);
  379.   temp.sel = temp.x + temp.y*64;
  380.  
  381.   this.tilemap[temp.sel] = 0;
  382.   onUpdateTileMap();
  383. }
  384.  
  385. // Drawing tool, draws the selected tiletype on the tile map
  386. function onChangeTileMap(temp.obj,temp.mod,temp.mx,temp.my) {
  387.   temp.local = temp.obj.globaltolocalcoord({temp.mx,temp.my});
  388.   temp.mx = temp.local[0];
  389.   temp.my = temp.local[1];
  390.  
  391.   temp.x = int(temp.mx/16);
  392.   temp.y = int(temp.my/16);
  393.   temp.sel = temp.x + temp.y*64;
  394.  
  395.   this.tilemap[temp.sel] = this.selectedBrush;
  396.   onUpdateTileMap();
  397. }
  398.  
  399. // Update the tile map control to reflect tile map
  400. function onUpdateTileMap() {
  401.   with (DustyShapeGen_MainTileMapControl) {
  402.     clearControls();
  403.  
  404.     for (temp.i=0;temp.i<thiso.tilemap.size();temp.i++) {
  405.       temp.ind = thiso.tilemap[temp.i];
  406.       if (temp.ind <= 0) continue;
  407.       temp.t = thiso.tileTypes[temp.ind];
  408.       new GuiControl() {
  409.         x = (temp.i%64)*16;
  410.         y = int(temp.i/64)*16;
  411.         width = height = 16;
  412.         useownprofile = true;
  413.         profile.border = 0;
  414.         profile.modal = false;
  415.         profile.bordercolor = {temp.t[1][0]/2,temp.t[1][1]/2,temp.t[1][2]/2};
  416.         profile.opaque = true;
  417.         profile.fillcolor = {temp.t[1][0],temp.t[1][1],temp.t[1][2],255};
  418.       }
  419.     }
  420.   }
  421. }
  422.  
  423. // A tiletype swatch selection has been made
  424. function selectType(temp.sel) {
  425.   // Remove border of all swatch controls
  426.   for (temp.i=0;temp.i<thiso.tileTypes.size();temp.i++) {
  427.     temp.t = thiso.tileTypes[temp.i];
  428.     with ("DustyShapeGen_Picker_ControlObject_" @ temp.t[0]) {
  429.       profile.border = 1;
  430.       profile.bordercolor = {temp.t[1][0]*.66,temp.t[1][1]*.66,temp.t[1][2]*.66};
  431.     }
  432.   }
  433.   // Give selected swatch control a border so we know it's selected
  434.   with ("DustyShapeGen_Picker_ControlObject_" @ temp.sel) {
  435.     profile.border = 1;
  436.     profile.bordercolor = {255,255,255,255};
  437.   }
  438.   this.selectedBrush = temp.sel;
  439. }
  440.  
  441. // Capture mouse input of swatch controls
  442. function onChangeBrush(temp.obj) {
  443.   selectType(temp.obj.brush);
  444. }
  445.  
  446. // Add a swatch for each tile type
  447. function addTypeControls() {
  448.   with (DustyShapeGen_Picker_Control) {
  449.     // Loop through all valid tile types
  450.     for (temp.i=0;temp.i<thiso.tileTypes.size();temp.i++) {
  451.       temp.t = thiso.tileTypes[temp.i];
  452.       // Skip tile types that aren't defined
  453.       if (temp.t.size() < 3) continue;
  454.       new GuiControl("DustyShapeGen_Picker_ControlObject_" @ temp.t[0]) {
  455.         x = 2;
  456.         y = 2 + temp.ind*22;
  457.         width = height = 20;
  458.         useownprofile = true;
  459.         profile.border = 0;
  460.         profile.bordercolor = {temp.t[1][0]/2,temp.t[1][1]/2,temp.t[1][2]/2};
  461.         profile.opaque = true;
  462.         profile.fillcolor = {temp.t[1][0],temp.t[1][1],temp.t[1][2],255};
  463.         this.brush = temp.t[0];
  464.         hint = temp.t[2];
  465.         hinttime = .1;
  466.  
  467.         thiso.catchevent(this,"onMouseDown","onChangeBrush");
  468.  
  469.         new GuiTextCtrl() {
  470.           style = "";
  471.           text = temp.t[0];
  472.           profile = GuiBlueTextProfile;
  473.           useownprofile = true;
  474.           profile.autosizewidth = profile.autosizeheight = false;
  475.           profile.modal = false;
  476.           profile.fonttype = "courier new";
  477.           profile.fontsize = 15;
  478.           profile.align = "center";
  479.           profile.textshadow = true;
  480.           profile.fontcolor =
  481.           profile.fontcolorhl =
  482.           profile.fontcolorna =
  483.           profile.fontcolorsel =
  484.           profile.fontcolorhl =
  485.           profile.fontcolorlink =
  486.           profile.fontcolorlinkhl = {255,255,255,255};
  487.  
  488.           profile.shadowcolor = {0,0,0,255};
  489.           x = text.length() < 2 ? 5 : 2;
  490.           y = -1;
  491.           width = 10;
  492.           height = 20;
  493.           cliptobounds = false;
  494.           clipchildren = false;
  495.         }
  496.       }
  497.       temp.ind++;
  498.     }
  499.   }
  500. }
  501.  
  502. // Update the background image
  503. function onUpdateImage(temp.i) {
  504.   // Detect whether image is an actual image or gani
  505.   if (temp.i.ends(".gani")) temp.i = extractfilebase(temp.i);
  506.   temp.isImage = temp.i.ends(".png") || temp.i.ends(".gif") || temp.i.ends(".mng");
  507.  
  508.   // Displace ganis due to the 0,0 position of a gani
  509.   with (DustyShapeGen_Main_Image) {
  510.     x = temp.isImage ? 0 : -8;
  511.     y = temp.isImage ? 0 : -16;
  512.     if (temp.isImage) image = temp.i;
  513.     else ani = temp.i;
  514.   }
  515. }
  516.  
  517. // Tiled background
  518. const BGTILE = "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";
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top