Thursday, November 27, 2008

Updating the DOxygen macros

So, after my interview at R* Vancouver (I have no idea what they actually call themselves) I thought I would update my Doxygen macros. The reason? I found some old source code that a co-worker of mine when I was at Radical (Neil Martin) had written and there were some tidbits in there that got me thinking about how I could update what I've got into something more manageable. I had a chance to look over the code last night and it was pretty sloppy. So the update gives me a chance to clean it up substantially. Functionality wise, not much has changed. I've created a lot more little functions that do very small things. For example, I've added a 'TimeStamp' function:
Function TimeStamp()
    Dim CurrentDate        
    CurrentDate = System.DateTime.Now.ToShortDateString()        
    Dim CurrentTime        
    CurrentTime = System.DateTime.Now.ToShortTimeString()        
    TimeStamp = "/// Time-stamp: <@(#)" & ActiveDocument.Name & "   " & CurrentDate & " - " & CurrentTime & "   " & Author() & ">"    
End Function
Which I then use like so:
Sub GenerateFileHeader()
    DTE.UndoContext.Open("Generate File Header")
    Try
        Dim linenumber As Integer
        DTE.ActiveDocument.Selection.StartOfDocument()
        Dim FileType
        Dim selection As TextSelection
        selection = DTE.ActiveDocument.Selection
        selection.Text = TimeStamp() & vbLf
        ...
Overall, this makes the code a lot cleaner to read. And a fair bit more manageable. The other thing that I added was the ability to automatically generate Header Guards (something I wanted to add, but was just too lazy last time to do it). As usual, to code follows, as well as a link to a downloadable version. Enjoy.
Imports SystemImports SystemImports EnvDTEImports EnvDTE80Imports System.DiagnosticsImports Microsoft.VisualBasicImports Microsoft.VisualBasic.ControlCharsPublic 
Module Documentation
    ' Check to see if our cursor (the TextSelection passed in) is currently at the first line
    Function OnFirstLine(ByVal selection As TextSelection)
        Return (selection.ActivePoint.Line = 1)
    End Function

    ' Generate a TimeStamp string
    Function TimeStamp()
        Dim CurrentDate
        CurrentDate = System.DateTime.Now.ToShortDateString()
        Dim CurrentTime
        CurrentTime = System.DateTime.Now.ToShortTimeString()
        TimeStamp = "/// Time-stamp: <@(#)" & ActiveDocument.Name & "   " & CurrentDate & " - " & CurrentTime & "   " & Author() & ">"
    End Function

    ' Generate a Doxygen 'Brief' tag, that the user can then populate
    Function Brief()
        Brief = "/// @brief   :"
    End Function

    ' Generate a 'Purpose' string that the user can populate.  Be intellegent about it,
    ' ensuring proper grammar for header as opposed to source files.
    Function Purpose()
        Dim FileType As String
        If InStr(DTE.ActiveDocument.Name, ".h") <> 0 Then
            FileType = "Declaration of class "
        Else
            FileType = "Implementation of methods for class "
        End If
        Purpose = "///  Purpose : " & FileType
    End Function

    ' Generate a DateStamp string
    Function DateStamp()
        Dim CurrentDate
        CurrentDate = System.DateTime.Now.ToShortDateString()
        DateStamp = "/// @date    :" & CurrentDate
    End Function

    ' Generate a simple Comment Line (no fancy decorations)
    Function CommentLine()
        CommentLine = "///"
    End Function

    ' Generate a DOxygen filename tag comment line
    Function FileName()
        FileName = "/// @file    :" & DTE.ActiveDocument.Name
    End Function

    ' Generate an DOxyge author tag comment line
    Function Author()
        ' Up to you, you can either use this function to automatically get the user name
        ' or put in a literal string.
        Author = "/// @author  :" & System.Environment.UserName
    End Function

    ' Generate a Decorated comment line separator
    Function CommentSeparatorLine()
        CommentSeparatorLine = "/// *********************************************************************"
    End Function

    ' Select the current line
    ' Are we actually using this?
    Function SelectCurrentLine()
        DTE.ActiveDocument.Selection.StartOfLine(0)
    End Function

    ' Generate a newline
    ' Question?  Are we actually using this?
    Function NewLine(ByVal selection As TextSelection)
        selection.NewLine()
        selection.StartOfLine()
    End Function

    ' Is the current file a Header file?
    Function IsHeaderFile()
        Dim fileName As String
        fileName = DTE.ActiveDocument().Name
        fileName = Right(fileName, fileName.Length() - InStr(fileName, "."))
        fileName = fileName.ToUpper()
        Return (fileName = "HPP") Or (fileName = "H")
    End Function

    ' Generate Header guards for our file
    Function GenerateHeaderGuards()
        Dim fileName As String
        Dim ifndef As String
        Dim define As String
        fileName = DTE.ActiveDocument().Name
        fileName = Left(fileName, InStr(fileName, ".") - 1)
        fileName = "__" + fileName + "_HPP__"
        fileName = fileName.ToUpper()
        ifndef = "#ifndef " + fileName + vbLf
        define = "#define " + fileName + vbLf + vbLf
        ActiveDocument.Selection.Text = ifndef + define
        ActiveDocument.Selection.EndOfDocument()
        ActiveDocument.Selection.Text = vbLf + "#endif // " + fileName
        ActiveDocument.Selection.StartOfDocument()
    End Function

    ' Generate the default Version history
    Function VersionHistory()
        Dim buffer As String
        Dim CurrentDate
        CurrentDate = System.DateTime.Now.ToShortDateString()
        buffer = "/// Version History:" + vbLf
        buffer = buffer + CommentLine() + vbLf
        buffer = buffer + "/// V 0.10  " & CurrentDate & " : First Revision" + vbLf
        buffer = buffer + CommentLine() + vbLf
        buffer = buffer + CommentSeparatorLine() + vbLf
        buffer = vbLf + vbLf
        VersionHistory = buffer
    End Function

    ' What's our return type for the given statement?
    Function GetReturnType(ByVal inStatement As String)
        Dim returnstring As String
        Dim statement As String
        statement = inStatement
        'Find first bracket
        If (InStr(statement, "(") <> 0) Then
            'This gets us the return value and function/method name
            statement = Left(statement, InStr(statement, "(") - 1)
            ' Strip off whitespaces (some people put a space before the '('
            statement = TrimAll(statement)
            Dim tokenArray() As String
            tokenArray = Split(Trim(statement), " ")
            If tokenArray.Length > 1 Then
                Dim index As Integer
                index = 0
                While index < tokenArray.Length - 1
                    returnstring = returnstring + tokenArray(index)
                    index = index + 1
                End While
                If returnstring.ToLower = "void" Then
                    returnstring = "/// "
                Else
                    returnstring = "/// @returns   :" & returnstring
                End If
            Else
                returnstring = "/// "
            End If
        End If
        GetReturnType = returnstring
    End Function

    ' Generate a paramater tag bundle from the given statement
    Function BuildParams(ByVal TextIn As String) As String
        Dim args As String
        Dim result As String
        Dim argsarray() As String
        args = Split(TextIn, "(")(1)
        args = Replace(args, ")", " ")
        args = TrimAll(args)
        argsarray = Split(args, ",")
        ' now for our args
        result = ""
        For Each arguement As String In argsarray
            Dim tokenArray() As String
            Dim character As Char
            tokenArray = Split(Trim(arguement), " ")
            result = result & "/// @param " & tokenArray(tokenArray.Length - 1) & vbLf
        Next
        BuildParams = result
    End Function

    ' Trim out all the unecessary fluff from a given string.
    Function TrimAll(ByVal TextIn As String) As String
        Try ' Replace ALL Duplicate Characters in String with a Single Instance
            Dim result As String
            result = TextIn
            result = Replace(result, vbTab, " ")
            result = Replace(result, vbNullChar, " ")
            result = Replace(result, vbCr, " ")
            result = Replace(result, vbLf, " ")
            result = Trim(result)
            TrimAll = result
        Catch Exp As Exception
            TrimAll = TextIn ' Oops
        End Try
        Return TrimAll
    End Function

    ' Generate the statement that we want to test
    Function GetStatement()
        Dim selection As TextSelection
        Dim statement As String
        Dim linenumber As Integer
        selection = DTE.ActiveDocument.Selection
        ' Get all the arguements from the method
        linenumber = selection.ActivePoint.Line
        selection.StartOfLine()
        selection.SelectLine()
        statement = TrimAll(selection.Text)
        Dim nextline As String
        Dim lastLine As Integer
        lastLine = linenumber
        While (InStr(statement, ")") = 0)
            selection.SelectLine()
            If lastLine <> selection.ActivePoint.Line Then
                nextline = TrimAll(selection.Text)
                statement = statement & nextline
            Else
                Exit While
            End If
        End While
        selection.GotoLine(linenumber)
        selection.StartOfLine()
        GetStatement = statement
    End Function

    Sub PerformDocumentation()
        Try
            Dim objTextDoc As TextDocument
            Dim editPoint As EnvDTE.EditPoint
            Dim selection As TextSelection
            Dim linenumber As Integer
            objTextDoc = DTE.ActiveDocument.Object("TextDocument")
            editPoint = objTextDoc.StartPoint.CreateEditPoint
            selection = objTextDoc.Selection
            linenumber = selection.ActivePoint.Line
            selection.StartOfLine()
            If OnFirstLine(selection) = True Then
                GenerateFileHeader()
            ElseIf selection.FindText("class") = True Then
     'Class declaration
                GenerateClassHeader()
            ElseIf selection.FindText("::") = True Then
     'Method definition
                GenerateMethodHeader()
            Else
                If selection.FindText("{") Then
             'Some Function definition
                    selection.GotoLine(linenumber)
                    GenerateFunctionHeader()
                End If
            End If
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
        End Try
    End Sub

    Sub GenerateMethodHeader()
        Dim selection As TextSelection
        DTE.UndoContext.Open("MethodHeader")
        Try
            selection = DTE.ActiveDocument.Selection
            ' Get all the arguements from the method
            Dim args As String
            Dim argsarray() As String
            Dim linenumber As Integer
            Dim statement As String
            statement = GetStatement()
            selection.NewLine()
            selection.StartOfLine()
            selection.Text = CommentSeparatorLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Brief() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = GetReturnType(statement) & vbLf
            selection.Text = BuildParams(statement)
            selection.Text = CommentSeparatorLine() & vbLf
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
            DTE.UndoContext.Close()
        End Try
    End Sub

    Sub GenerateFunctionHeader()
        Dim selection As TextSelection
        DTE.UndoContext.Open("FunctionHeader")
        Try
            selection = DTE.ActiveDocument.Selection
            ' Get all the arguements from the method
            Dim args As String
            Dim argsarray() As String
            Dim linenumber As Integer
            Dim statement As String
            statement = GetStatement()
            selection.NewLine()
            selection.StartOfLine()
            selection.Text = CommentSeparatorLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Brief() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = GetReturnType(statement) & vbLf
            selection.Text = BuildParams(statement)
            selection.Text = CommentSeparatorLine() & vbLf
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
            DTE.UndoContext.Close()
        End Try
    End Sub

    Sub GenerateClassHeader()
        DTE.UndoContext.Open("ClassHeader")
        Try
            Dim selection As TextSelection
            Dim linenumber As Integer
            selection = DTE.ActiveDocument.Selection
            selection.StartOfLine()
            selection.NewLine()
            selection.StartOfLine()
            selection.Text = CommentSeparatorLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Brief() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = CommentSeparatorLine() & vbLf
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
        Finally
            DTE.UndoContext.Close()
        End Try
    End Sub

    Sub GenerateFileHeader()
        DTE.UndoContext.Open("Generate File Header")
        Try
            Dim linenumber As Integer
            DTE.ActiveDocument.Selection.StartOfDocument()
            Dim FileType
            Dim selection As TextSelection
            selection = DTE.ActiveDocument.Selection
            selection.Text = TimeStamp() & vbLf
            selection.Text = CommentSeparatorLine() & vbLf
            selection.Text = FileName() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = Author() & vbLf
            selection.Text = DateStamp() & vbLf
            selection.Text = CommentLine() & vbLf
            linenumber = selection.ActivePoint.Line ' This is where we want to return to
            selection.Text = Purpose() & vbLf
            selection.Text = CommentLine() & vbLf
            selection.Text = Brief() & vbLf
            selection.Text = CommentSeparatorLine() & vbLf
            selection.Text = VersionHistory() & vbLf
            If IsHeaderFile() = True Then
                GenerateHeaderGuards()
            End If
            selection.GotoLine(linenumber)
            selection.EndOfLine()
        Catch ex As Exception
            Dim messagebox As System.Windows.Forms.MessageBox
            messagebox.Show(ex.Message)
        Finally
            DTE.UndoContext.Close()
        End Try
    End
 SubEnd
 Module
Download here: http://ash.matheson.googlepages.com/Documentation.rar

Wednesday, November 19, 2008

QT and Ogre

So, during my time off, I've started looking at QT (something I used at Radical a ways back ... when it was at 3.3 or so) and Ogre. True to what I was just recently doing at my last job, I thought I'd give a go at using both for a world editor. So, I've been used to using wxWidgets for the last couple of years. There's things I like about it (Free, source code included and DialogBlocks is a relatively nice/non-retarded gui builder) and some things I don't like about it (it's free, so there's little support for it, subclassing compound widgets is a royal pain in the tuckas ). Anyway, what I wanted to start with was a simple window, with a menu, a status bar and a widget that encompassed a render context. So, I crack open the designer tool and go to work building a simple app. I create a mainwindow gui. This is nice because it comes with a menu, docking toolbar and status bar all ready to go. Then I add a widget (just a simple one) to the main window and then try to get it to fit completely in the layout. This is a nightmare, because I'm used to how Dialogblocks works (you know, in a way that makes sense). Apparently you have to click on the main background and do some fancy 'layout fitting' garbage. Completely non-intuitive. Not a good start, if you ask me. Anyway, I work a little more, trying to figure out how to use the Designer to create a subclass of a QWidget that would represent my new render window. Not easy, but significantly less tricky than layout. Now that's done, I start trying to bind Ogre to the window. This is where it all falls apart. Like a lot of these SDKs, the documentation is woefully inadequate. As soon as I get the widget ready to start rendering my window, I get nothing. Until I resize my window. Then I get this god-awful tearing of the widget and the Ogre based render. So, this leads me to believe that I've improperly overridden the paint method of the QWidget class. I dig and I dig and I dig, but everything I read about subclassing widgets tells me that I'm doing the right thing. That is until I read somewhere on a web site that in QT 4+, each widget automatically double buffers. So, somewhere in the deep internals of QT, they have a hidden swap chain that I have no idea how to override. So, after lots and lots of digging, I finally figure out what I need to set as part of the derived objects construction attributes. So, for a class like so:
#ifndef __RENDERWINDOW_H__
#define __RENDERWINDOW_H__
#include 
#include "context.h"
QT_BEGIN_NAMESPACE
/// *********************************************************************
/// @brief A RenderWindow is a Widget that is used for rendering
/// The RenderContext performs our rendering, but this class manages
/// all the window level refreshing.
/// 
/// *********************************************************************
class RenderWindow :    public QWidget
{
public:
    RenderWindow(void);
    RenderWindow ( QWidget * parent = 0, Qt::WindowFlags f = 0 );
    ~RenderWindow(void);
    virtual void showEvent( QShowEvent * event );
    virtual void paintEvent( QPaintEvent * event );
    virtual void resizeEvent(QResizeEvent *evt);
    void Init( void );
    void Update( void );
protected:
    RenderContext   m_RenderContext;
    bool            m_WindowInitialized : 1;
  };
QT_END_NAMESPACE
#endif
 // __RENDERWINDOW_H__
And where RenderContext is a class I've derived for doing the actual binding to Ogre, we need a constructor that looks like this:
/// *********************************************************************
/// @brief unparameterized Constructor for the Renderwindow
/// Note that we have to set the following attributes to disable QT's
/// double buffering, which was causing all sorts of flickering
/// 
/// *********************************************************************
RenderWindow::RenderWindow(void)   : m_WindowInitialized( false )
{
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_NoSystemBackground);
    setAutoFillBackground( false );
}

/// *********************************************************************
/// @brief Parameterized Constructor for the RenderWindow
/// Note that we have to set the following attributes to disable QT's
/// double buffering, which was causing all sorts of flickering
/// 
/// @param parent Parent Window
/// @param f      Additional window creation flags
/// *********************************************************************
RenderWindow::RenderWindow( QWidget * parent, Qt::WindowFlags f ): QWidget( parent, f ),  m_WindowInitialized( false )
{
    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_NoSystemBackground);
    setAutoFillBackground( false );
}
As well, make sure you override the painting method as well:
/// *********************************************************************
/// @brief Handler for the paint event (overridden from the virutal base)
/// In this, we're simply calling the RenderWindow's Update Method.
/// 
/// @param event the event to process (which we don't)
/// *********************************************************************
void RenderWindow::paintEvent( QPaintEvent * event )
{
    Update();
}

/// *********************************************************************
/// @brief Update our RenderWindow/// We update one frame of the rendercontext
/// 
/// *********************************************************************void RenderWindow::Update( void )
{
    g_SceneManager->GetSceneRoot()->_fireFrameStarted();
    m_RenderContext.Update( );
    g_SceneManager->GetSceneRoot()->_fireFrameEnded();
}
And that seems to work fine. As I progress more with this, I'll update with new details.

Tuesday, November 18, 2008

DOxygen and Dev Studio

So, with a little more time on my hands, I've been working on some portfolio stuff. For me, this means coding. Now at work, I had a handily little macro that I had scavenged together that added DOxygen comments to my code (bound to a keypress). Unfortunately, I left all that at work (and I don't have it backed up anywhere).

I've also had some time to play around with some CSS and jScript from Google code. This is pretty neat: http://code.google.com/p/syntaxhighlighter/ and it was very easy to add to this blog. It supports a variety of languages and looks awesome. I recommend you try it!

So, this was an excellent opportunity for me to create a new one and post it here. As well, I can discuss some of the things I ran into along my way.

It's pretty simple how I went about developing this set of macros. First off, I wanted one 'entry' function for determining what kind of comment I was making. This was pretty simple, and the method I used for determining if I'm commenting the top of a file, a class, a method or a function is pretty straightforward (potentially not the best, but I'll juice that up as time goes on). I boil it down to this:

a) if the current line is line zero, it's a file header comment.
b) if the current line contains a 'class' keyword, we're documenting a class
c) if the current line contains a '::', we're documenting a method
d) if the next line has a '{', it's a function

Like I said, it's pretty simple (read: stupid) but I'll enhance it later.

After that, it's just a matter of populating the comments with the right data.

Now, I did run into an interesting problem (which is where the majority of my day went). One thing I wanted to do was process all my method parameters and generate documentation for them. So, the process for that went like this:

1) generate an 'arguments' string. This is essentially everything between the '(' and ')'. This is a little problematic, because I need to deal with parameters that are spread across multiple lines. This was pretty easy to do. Then came stripping out the unnecessary characters (left and right trimming the '(' and ')' characters). I figured that I could do a string replace for all '(' and ')' characters with a space. Then use the Trim function in vb to strip out what I didn't want. However, I noticed that I was still having spaces at the end of my string. Or at least what I thought was spaces. It took a while for me to realize that they were non-printable characters ( specifically, there was a carriage return embedded before my ')' ... which wasn't in the source file). Anyway, there's a host of other reasons why I'd want to get rid of additional characters in my argument list, so I built a function that trimmed out additional 'fluff' characters, including tabs, line feeds, carriage returns and a few other non-printable characters). And then Trimmed the results. The code looks like this:

First, creating the argument string:
' Get all the arguments from the method
Dim args As String
Dim linenumber As Integer
selection.SelectLine()
args = selection.Text

' strip off the method return/method name (everything before the '('
Dim argsarray() As String = Split(args, "(")
Dim nextline As String
args = argsarray(1)

While InStr(args, ")") = 0
selection.LineDown()
nextline = selection.Text
args = args & nextline
End While

args = Replace(args, ")", " ")
args = TrimAll(args)
argsarray = Split(args, ",")
selection.GotoLine(linenumber)


Second, the TrimAll function:
Function TrimAll(ByVal TextIn As String) As String
Try ' Replace ALL Duplicate Characters in String with a Single Instance
Dim result As String
result = Replace(TextIn, ")", " ")
result = Replace(result, vbTab, " ")
result = Replace(result, vbNullChar, " ")
result = Replace(result, vbCr, " ")
result = Replace(result, vbLf, " ")
result = Trim(result)
TrimAll = result

Catch Exp As Exception
TrimAll = TextIn ' Oops
End Try

Return TrimAll

End Function


2) tokenize the arguments. VB has a 'split' function that breaks a string up into a string array based on a delimiter character. So, to break it down into arguments, it's a matter of splitting on a ',' character. After this, use VB's 'For Each' iterator to walk over the array of arguments and then tokenize each argument into another string array to get a list of types and variables. Simply grabbing the last array element gives me my variable name, which I can then print out.

OK. So after all that, here's the full code listing. Copy and paste into a new module. You'll probably want to change the 'Ash Matheson' to something more appropriate.
---------------------------------------cut here------------------------------------
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module Documentation
Function TrimAll(ByVal TextIn As String) As String

Try ' Replace ALL Duplicate Characters in String with a Single Instance
Dim result As String
result = Replace(TextIn, ")", " ")
result = Replace(result, vbTab, " ")
result = Replace(result, vbNullChar, " ")
result = Replace(result, vbCr, " ")
result = Replace(result, vbLf, " ")
result = Trim(result)
TrimAll = result

Catch Exp As Exception
TrimAll = TextIn ' Oops
End Try

Return TrimAll

End Function
Sub PerformDocumentation()
Try
Dim objTextDoc As TextDocument
Dim editPoint As EnvDTE.EditPoint
Dim selection As TextSelection

objTextDoc = DTE.ActiveDocument.Object("TextDocument")
editPoint = objTextDoc.StartPoint.CreateEditPoint
selection = objTextDoc.Selection
selection.StartOfLine()

If selection.ActivePoint.Line = 1 Then
GenerateFileHeader()
ElseIf selection.FindText("class") = True Then  'Class declaration
GenerateClassHeader()
ElseIf selection.FindText("::") = True Then     'Method definition
GenerateMethodHeader()
Else
selection.LineDown()
If selection.FindText("{") Then             'Some Function definition
selection.LineUp()
GenerateFunctionHeader()

End If
End If

Catch ex As Exception
Dim messagebox As System.Windows.Forms.MessageBox
messagebox.Show(ex.Message)

Finally

End Try
End Sub
Sub GenerateMethodHeader()
DTE.UndoContext.Open("MethodHeader")
Try
Dim selection As TextSelection
selection = DTE.ActiveDocument.Selection

' Get all the arguements from the method
Dim args As String
Dim linenumber As Integer
linenumber = selection.ActivePoint.Line
selection.SelectLine()

args = selection.Text

' strip off the method return/method name (everything before the '('
Dim argsarray() As String = Split(args, "(")
Dim nextline As String
args = argsarray(1)
While InStr(args, ")") = 0
selection.LineDown()
nextline = selection.Text
args = args & nextline
End While
args = Replace(args, ")", " ")
args = TrimAll(args)

argsarray = Split(args, ",")

selection.GotoLine(linenumber)
selection.StartOfLine()
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @brief "
linenumber = selection.ActivePoint.Line ' This is where we want to return to
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @return "

' now for our args
For Each arguement As String In argsarray
Dim tokenArray() As String
Dim character As Char

selection.NewLine()
selection.StartOfLine()

tokenArray = Split(Trim(arguement), " ")
selection.Text = "/// @param " & tokenArray(tokenArray.Length - 1)

Next

selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()

selection.GotoLine(linenumber)

Catch ex As Exception
Dim messagebox As System.Windows.Forms.MessageBox
messagebox.Show(ex.Message)

Finally
DTE.UndoContext.Close()
End Try

End Sub
Sub GenerateFunctionHeader()
DTE.UndoContext.Open("FunctionHeader")
Try
Dim selection As TextSelection
selection = DTE.ActiveDocument.Selection

' Get all the arguements from the method
Dim args As String
Dim linenumber As Integer
selection.SelectLine()
args = selection.Text

' strip off the method return/method name (everything before the '('
Dim argsarray() As String = Split(args, "(")
Dim nextline As String
args = argsarray(1)
While InStr(args, ")") = 0
selection.LineDown()
nextline = selection.Text
args = args & nextline
End While
args = Replace(args, ")", " ")
args = TrimAll(args)

argsarray = Split(args, ",")

selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @brief "
linenumber = selection.ActivePoint.Line ' This is where we want to return to
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @return "
' now for our args
For Each arguement As String In argsarray
Dim tokenArray() As String
Dim character As Char

selection.NewLine()
selection.StartOfLine()

tokenArray = Split(Trim(arguement), " ")
selection.Text = "/// @param " & tokenArray(tokenArray.Length - 1)

Next
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"

selection.GotoLine(linenumber)

Catch ex As Exception

Finally
DTE.UndoContext.Close()
End Try

End Sub
Sub GenerateClassHeader()
DTE.UndoContext.Open("ClassHeader")
Try
Dim selection As TextSelection
Dim linenumber As Integer

selection = DTE.ActiveDocument.Selection

selection.StartOfLine()
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @brief "
linenumber = selection.ActivePoint.Line ' This is where we want to return to
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()

selection.GotoLine(linenumber)
selection.EndOfLine()

Catch ex As Exception
Finally
DTE.UndoContext.Close()
End Try
End Sub
Sub GenerateFileHeader()
DTE.UndoContext.Open("Generate File Header")
Try
DTE.ActiveDocument.Selection.StartOfDocument()
Dim CurrentDate
CurrentDate = System.DateTime.Now.ToShortDateString()
Dim CurrentTime
CurrentTime = System.DateTime.Now.ToShortTimeString()
Dim Author = "Ash Matheson"
Dim FileType
Dim selection As TextSelection
selection = DTE.ActiveDocument.Selection

selection.Text = "/// Time-stamp: <@(#)" & ActiveDocument.Name & "   " & CurrentDate & " - " & CurrentTime & "   " & Author & ">"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @file   : " & ActiveDocument.Name
selection.NewLine()
selection.StartOfLine()
selection.Text = "///"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @author " & Author
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @date  " & CurrentDate
selection.NewLine()
selection.StartOfLine()
selection.Text = "///"
selection.NewLine()
selection.StartOfLine()
If InStr(ActiveDocument.Name, ".h") <> 0 Then
FileType = "Declaration of class "
Else
FileType = "Implementation of methods for class "
End If
selection.Text = "///  Purpose : " & FileType
selection.NewLine()
selection.StartOfLine()
selection.Text = "///"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// @brief "
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// Version History:"
selection.NewLine()
selection.StartOfLine()
selection.Text = "///"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// V 0.10  " & CurrentDate & "  BN : First Revision"
selection.NewLine()
selection.StartOfLine()
selection.Text = "///"
selection.NewLine()
selection.StartOfLine()
selection.Text = "/// *********************************************************************"
selection.NewLine()
selection.StartOfLine()
selection.NewLine()
selection.NewLine()

Catch ex As Exception
Dim messagebox As System.Windows.Forms.MessageBox
messagebox.Show(ex.Message)

Finally
DTE.UndoContext.Close()
End Try

End Sub

End Module

---------------------------------------cut here------------------------------------
linkage, for downloading: link

Thursday, November 13, 2008

Off to Unemployment land I go

So, today I got the big "Heave Ho" at Hothead. Yay. Great timing just before Christmas. But what are you gonna do? Anyway, I thought that during this time off, I'd journal the process, since it's been a very, very long time since I've been on this side of the employment fence.

Wednesday, June 25, 2008

Perforce and figuring out what you've got

Perforce can be pretty great. And sometimes it can be just ass. Here's an example:
I want to know what my current changelist is. There's no visual tool to find out (maybe there is in the new, Java based tool that is complete and utter ASS, but I refuse to use it). So you have to go to the command line. And it's pretty esoteric:
p4 changes -m1 #have<br />

Without the #have option, what you get it pretty much useless. And it's poorly documented that you need to have the #have option (#have isn't even documented, from what I can tell).

Wednesday, May 14, 2008

On Zen and Music

So, a couple of weekends ago, I reformatted my home machine. No biggie, got everything situated nicely. And I think I'm good to go.

Then I try to hook my my Creative Labs Zen Vision M: 30 to it.

No amount of tomfoolery could get my pc to recognize it. None. I was completely flabbergasted by this. I had no idea what was wrong with it.

That is, until I realized that it was looking for an MTC driver. Which, after some digging, is only distributed with Windows Media player.

So, in order for my MP3 player to connect to my XP PC, I have to install Windows Media player (Version 10 and up).

That, my good friends, is completely retarded. I can't even grab the appropriate drivers from Creative Labs because *they don't exist*.

Thursday, May 01, 2008

Cygwin command

So, I've been using Cygwin + putty for the last couple of years (it's a much better replacement for a shell than cmd.exe), but one thing has been annoying me about it. For the life of me, I couldn't figure out how to clear the screen.

That is, until today, when I accidentally pressed "Ctrl + L" at the same time. Voila, clear screen.

Some testing shows that it also works on the plain Jane Cygwin terminal as well. Shame I hadn't figured that out earlier.

Wednesday, January 09, 2008

Look! Two Updates in a week

So, a little news about the studio I work at.

[edit:] Gamasutra linkage here:

http://www.gamasutra.com/php-bin/news_index.php?story=16883


Via the Hothead Newspage:

http://www.hotheadgames.com/news15.php?ref=inside


Annnnd ...

http://grumpygamer.com/8519854


That's right. Ron Gilbert's our new Creative Director. I'm really, really stoked about this.

Very interesting times to come, folks.

Tuesday, January 08, 2008

So, now that I've finally got Rock Band ...

I get this link this morning:

http://www.gearlog.com/2008/01/guitar_hero_air_guitar_rocker.php


In short, it's a belt buckle that has a 'virtual' pick that when you strum over it, it plays a bit of music. Like you're playing guitar. And it's being shipped in March.

I think I want this. Just to annoy the crazies on the Skytrain.