Monday, 29 February 2016

Problem with handling HTML form checkboxes in php

php doesn't handle checkboxes properly in html forms. If you use

My Checkbox <input type="checkbox" name="my_checkbox" id="my_checkbox"'.($current_value?'checked':'').' />

You'll only get a result for isset($_REQUEST['my_checkbox']) if the box is *checked*, not if it's cleared. So you can't test for whether the box was unchecked by the user, because using !isset would be the same whether the page was just loaded, or if the form was submitted with the box unchecked by user input.

The solution from Stack Overflow:

Every checkbox generated is associated with a hidden field of the same name, placed just before the checkbox, and with a value of "0".

<input name="my_checkbox" type="hidden" value="0" />
<input name="my_checkbox" type="checkbox" value="1" />


Then isset($_REQUEST['my_checkbox']) always returns true if the box was modified, and false if the page was just loaded. And you'll always get the correct '0' or '1' value in $_REQUEST['my_checkbox'].

Thursday, 25 February 2016

How to create a plugin for Lumberyard

Lumberyard/CryEngine uses waf, a build configuration system similar to CMake.

To add a plugin project, create a subdirectory NewPlugin in dev/Code (a plugin might go in dev/Code/Sandbox/Plugins for example).

Add a wscript file to this directory, looking like this:

 
def build(bld): 
 
 bld.CryPlugin(
  target = 'NewPlugin',
   vs_filter = 'Sandbox/Plugins',
        file_list   = 'newplugin.waf_files',
  features =  ['qt'],
  includes = [
            '.',
            '..'
        ],
  use='EditorCommon'
 )
And add a file newplugin.waf_files, looking like:
{
 "NoUberFile": 
 {
  "Root":
  [
   "NewPlugin.cpp",
   "NewPlugin.h"
  ]
 }
}
Then go to dev/_WAF_/specs, and edit all.json. Add "NewPlugin" to the win_profile_modules and win_debug_modules list. Finally, recreate the solution by opening a command prompt in dev/ and running "lmbr_waf configure"

Sunday, 14 February 2016

The Three Hierarchies of C++

Lest anyone ever tell you programming isn't complicated, it occurred to me that a C++ program has three interlocking, but independent hierarchies.

  • Namespace: The name of the function, within its parent namespace and/or the class that owns it.
  • Call Stack: The parent is the calling function, the child is the callee.
  • Inheritance: The class/struct is a child of the base class.

Could we stand to lose one or two of these?

Friday, 12 February 2016

Reverting all deletes in Git, leaving file modifications in place

I asked how to do this on StackOverflow, and the answer is:

git diff --diff-filter=D --name-only | xargs git checkout

You need the "xargs": just piping the output of "diff" to "checkout" doesn't work.

Sunday, 24 January 2016

Minimal Hello World for FASTBuild

FASTBuild is an open source build program with amazing potential. It apparently allows distributed compilation out-of-the-box, which is something Incredibuild charge a lot of money for. But the documentation is minimal so far, and it lacks a functional example. So I put together a "Hello World" for FASTBuild. The HelloWorld.cpp is:

#include <iostream>

int main(int , char * [])
{
 std::cout << "hello world!\n";
 return 0;
}

And the project config file is build.bff:

;-------------------------------------------------------------------------------
; Windows Platform
;-------------------------------------------------------------------------------
.VSBasePath  = 'C:/Program Files (x86)/Microsoft Visual Studio 12.0'
.WindowsSDKBasePath = 'C:/Program Files (x86)/Windows Kits/8.1'
.ClangBasePath  = 'C:/Program Files/LLVM'
.WindowsLibPaths = '$WindowsSDKBasePath$/lib/winv6.3/um'


.BaseIncludePaths  = ' /I"./"'
    + ' /I"$VSBasePath$/VC/include/"'
    + ' /I"$WindowsSDKBasePath$/include/um"'
    + ' /I"$WindowsSDKBasePath$/include/shared"'

Compiler( 'Compiler-x86' )
{
 .Root  = '$VSBasePath$/VC/bin'
 .Executable = '$Root$/cl.exe'
}
; MSVC Toolchain
;---------------
.ToolsBasePath  = '$VSBasePath$/VC/bin'
.Compiler  = 'Compiler-x86'
.Librarian  = '$ToolsBasePath$/lib.exe'
.Linker   = '$ToolsBasePath$/link.exe'
.CompilerOptions = '%1 /Fo%2 /c /Z7'
.CompilerOptions + .BaseIncludePaths
.LibrarianOptions = '/NODEFAULTLIB /OUT:%2 %1'
.LinkerOptions  = ' /OUT:%2 %1 /SUBSYSTEM:CONSOLE'
.LinkerOptions  +  ' /LIBPATH:"$WindowsLibPaths$/x86" /LIBPATH:"$VSBasePath$/VC/lib"'

; Libraries
;----------
Library( 'exelib' )
{
    .CompilerInputPath = '.\\'
    .CompilerOutputPath= 'Out\'
    .LibrarianOutput   = 'Out\exelib.lib'
}
; Executables
;------------
Executable( 'myExe' )
{
 .CompilerInputPath = '.\'
 .CompilerInputPattern    ='*.cpp'
 .CompilerOutputPath= 'Out/'
 .Libraries    = { 'exelib' }
 .LinkerOutput = 'HelloWorld.exe'
 .LinkerOptions + ' /SUBSYSTEM:CONSOLE'
   + ' LIBCMT.LIB'
}

; 'all'
;-------
Alias( 'all' )
{
   .Targets = { 'myExe' }
}


To build it, go to the directory in a command prompt and run FBuild.exe.
This is for Visual Studio 2013 (12.0) - for different versions just change the VSBasePath variable.

One really interesting thing is that you can't seem to compile source files into Executables directly: you have to specify a library (e.g. "exelib" above), and use .CompilerInputPath to specify a directory. It will scan the path for all files of interest (.cpp by default) - you can specify them individually if you want. But the Executable command doesn't compile cpp's and if you don't include a library, it will complain of having no Object files to link.

Update 27/1/2016

FASTBuild author Franta Fulin has posted an official Hello World example: you can find it here.

Tuesday, 19 January 2016

$(VCTargetsPath) in MSBuild

MSBuild may fail to build, complaining that
"C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.Cpp.Default.props" was not found
i.e. trying to load the v110 toolset even though you may not have the corresponding Visual Studio version. To fix it, set the environment variable VisualStudioVersion=12.0 for example, or pass it to msbuild on the command line as /p:VisualStudioVersion=12.0.

Friday, 8 January 2016

Visual Studio-style mouse controls for Sublime Text

Create C:\Users\(YOURNAME)\AppData\Roaming\Sublime Text 3\Packages\User\Default (Windows).sublime-mousemap, and fill it with:

[
  // Ctrl-click word select
    {
        "button": "button1", "count": 1, "modifiers": ["ctrl"],
        "press_command": "drag_select",
        "press_args": {"by": "words"}
    }
  // Column select
  ,{
        "button": "button1", 
        "count": 1, 
        "modifiers": ["alt"],
        "press_command": "drag_select",
        "press_args": {"by": "columns"}
  }
]