Click here to load JAG Reloaded
Who's Online
7 registered (GeneralArthur, Gorro der Grüne, DepressivesBrot, Damienov, blueskirt, 2 invisible), 16 Guests and 4 Spiders online.
Key: Admin, Global Mod, Mod
Topic Options
Rate This Topic
#181093 - 12 April, 2008 09:05 AM Laptop files section
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany
Hi everybody!

I just downloaded the source code and browsed a bit around in the different files. One (of the many things) that I cannot figure is how and where is drawing things on the screen actually done?

I am no professional programmer nor do I have much experience in c++ but I would like to contribute a bit. For me it seemed as if externalizing the laptop "files" could be a starting point for me as this would provide the possibility to dive into the topic of XML-reading and probably drawing.

My idea is based onto the following XML-file layout:

 Code:
<?xml version="1.0" encoding="utf-8"?>
<DOCUMENT>
	<Name>Sample Document Name</Name>
	<uiListPosition>0</uiListPosition>
	<uiPages>1</uiPages>
	<TRIGGERS>
		<!-- see forum topic on externalized Airports -->
		<TRIGGER>
			<SectorPlayerControlled>B13</SectorPlayerControlled>
			<SpokeToNPC>
				<NPCProfileNo>114</NPCProfileNO>
				<DialogChoice>2</DialogChoice>
				<TestLDRSkill>1</TestLDRSkill>
			</SpokeToNPC>
		</TRIGGER>
		<TRIGGER>
			<PlayerProgressAt>57</PlayerProgressAt>
		</TRIGGER>
	</TRIGGERS>
	<PAGES>
		<PAGE>
			<uiIndex>0</uiIndex>
			<uiBoxes>1</uiBoxes>
			<BOXES>
				<BOX>
					<uiIndex>0</uiIndex>
					<uiType>0<uiType>
					<uiPositionLeft>10</uiPositionLeft>
					<uiPositionTop>10</uiPositionTop>
					<uiPositionWidth>150</uiPositionWidth>
					<uiPositionHeight>100</uiPositionHeight>
					<FontSize>15</FontSize>
					<FontStyle>0</FontStyle>
					<FontColor>...</FontColor>
					<uiTextIndex>index of localized text entry in some other XML file</uiText>
					<Image>Path to image file relative to some folder..<Image>
				</BOX>
			</BOXES>
		</PAGE>
	</PAGES>
</DOCUMENT>


A "document" in the files-browser would consists of a one or more "pages", each of which could be accessed by the well-known arrow-buttons.
A "page" is divided into one or more "boxes", whereas each box can contain either formatted text or an image (placed in the same folder as the xml, png-format!).

A number of such files would be placed in some folder (for ex. "\Laptop\Files"). On opening the files section of the laptop all xml-files in this folder would be read, the specific TRIGGERS-section evaluated and finally all matching entries draw in the files list on the left.


Problem is: while I probably could figure out how to read an xml into some sort of class-hierarchy I have no clue how to draw the whole thing onto the screen. For png-decoding I would propose to use libpng.



Please comment on this idea.

best regards
Arne
Offline - OFFLINE
Top
#181100 - 12 April, 2008 09:48 AM Re: Laptop files section [Re: lochkartenman]
Tron

Drill Sargeant
Drill Sergeant

Posts: 295
Loc: Germany
Drawing the "laptop files" is hard-coded in Build/Laptop/files.cpp (Build/Laptop/files.c in the vanilla source code, Build/Laptop/Files.c in JA2-Stracciatella). There's nothing spectacular, just messy code to blit some pictures and draw text.
_________________________
Jagged Alliance 2 - Stracciatella - Bringing JA2 to SDL and everywhere
Offline - OFFLINE
Top
#181102 - 12 April, 2008 10:03 AM Re: Laptop files section [Re: Tron]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany
@Tron Thanks for pointing me to the source file.

What library is used by Ja2 for drawing basic things such as images, lines, rectangles, text? Where do I get a reference to some sort of drawing surface?
Offline - OFFLINE
Top
#181159 - 12 April, 2008 05:03 PM Re: Laptop files section [Re: lochkartenman]
BirdFlu
Lieutenant
Lieutenant

Posts: 562
Loc: Lampukistan
LOL.
Look at the files vobject.*, vobject_blitters.*, vsurface.* in the 'Standard Gaming Platform' directory. But i warn you, you won't like what you are going to see.
Offline - OFFLINE
Top
Badges:
#181165 - 12 April, 2008 06:55 PM Re: Laptop files section [Re: BirdFlu]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany
Had a look at these things. BirdFlu - you are right. I dont like it. After all: comments and structuring are totally overrated. (sarcasm!)

I will need some time to go into this. A am a bit spoiled by all this object-orientied stuff they tell you on university it seems. I'll dive into it but don't expect me back on the surface to soon.

best regards Arne

EDIT: By the way - is there any chance to get any decent GUI-toolkit (Qt, wxWidgeds, ..) incorporated into the game? For me it seems unnecessary to home-brew every thing if there are proven and well desinged libraries around.


Edited by lochkartenman (12 April, 2008 06:59 PM)
Offline - OFFLINE
Top
#181198 - 13 April, 2008 04:15 AM Re: Laptop files section [Re: lochkartenman]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany
I further investigated the laptop & drawing code. I must admit: I am not amused. The whole thing a mess and if it were my code I would probably start all over and rewrite it - but I sense that this would exceed my abilities a bit.

I took the time to read some tutorials related to DirectDraw and realized that my idea of using GUI-toolkits was a bit too naive. So please pretend the comment weren't there. :-)

The question that remain is: does it make sense to put any effort into the GUI at this time or will the - hopefully - upcoming transition to an other tile engine also affect all other drawing stuff, thus making those changes done to the drawing code obsolete?

Since the game has a quite limited set of screens besides the tile engine, would it be feasible to simply rewrite the whole interface in a more streamlined manner and use the "old" tile engine beside the rewritten interface?

regards Arne
Offline - OFFLINE
Top
#181224 - 13 April, 2008 08:16 AM Re: Laptop files section [Re: lochkartenman]
Kaiden

Captain
Captain

Posts: 1832
If all you want to do is add laptop files, web-pages, e-mails, etc... There is no need to rip everything out from the ground up. Use what's there. Expand on it, learn it. Then after you've used it repeatedly, been through it, pulled your hair out over having to use it, then think about replacing it.
_________________________
JA2 - 1.13 MOD [Coder]
Download it,Review it, and Rate it @ MOD DB
JA2 1.13 Wiki
NOT True is the new False.
Offline - OFFLINE
Top
Badges:
#181588 - 15 April, 2008 01:05 PM Re: Laptop files section [Re: Kaiden]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

Hi there.

I would like to post here what I've come up with so far. Consider this a proof-of concept since drawing formatted text on the screen is obviously only part of the task. How to draw images is the next issue I will tackle.

Reading the XML-file seems quite straight forward to me since there is plenty "sample code" already.

What the code does: print a null-terminated CHAR16 array to a screen rectangle. Characters enclosed by [b] ... [/b] are printed bold. [nl] indicates a line break. Text alignment is specified for each text area.



For anyone interested the source code:

FormattedTextRenderer.h

 Code:
#ifndef __FORMATTEDTEXTRENDERER_H
#define __FORMATTEDTEXTRENDERER_H

/******************************************************************************
	Name	:	class FormattedTextRenderer
	Created	:	04/14/2008
	Author	:	ARNE (Lochkartenman)

	Class used for parsing and rendering a text string (CHAR16 array)
	with embedded formatting tags similar to BB-Codes.

	This class was developed for use in the laptop files screen but should
	be easily adaptable to other text rendering tasks


	REMARKS:
	Italic-style is not yet implemented because Ja2 uses a fixed set of fonts.
	If this system is ever reverted to use the appropiate Windows-API or if
	italic fonts are added then this feature might be very well possible.

	Coloring of Text is planned and should be possible with not too much effort.
	I hold this back for now to concentrate on the actual externalizing part
	for the laptop files and IMAGES.

	Revision:	04/15/2008	- initial release

******************************************************************************/
class FormattedTextRenderer
{

public:

	/**************************************************************************
		structure representing a rectagle
	*/
	struct Rectangle
	{

	public:
		UINT16 Top;			// Y-coord. of upper left corner
		UINT16 Left;		// X-coord. of upper left corner
		UINT16 Width;		// width of rectangle
		UINT16 Height;		// height of rectangle

		/********************************************************************** 
			contructor initializes the structure with values
			
			UINT16 Top;			- Y-coord. of upper left corner
			UINT16 Left;		- X-coord. of upper left corner
			UINT16 Width;		- width of rectangle
			UINT16 Height;		- height of rectangle
		*/
		Rectangle(UINT16 top, UINT16 left, UINT16 width, UINT16 height)
		{
			Top = top;
			Left = left;
			Width = width;
			Height = height;
		}

	};

	/**************************************************************************
		enumeration of possible text alignments
	*/
	enum TextAlignmentEnum
	{
		Left,
		Right,
		Centered
	};

	/****************/
	/* CONSTRUCTORS */
	/****************/

	FormattedTextRenderer(void);	
	
	/***********/
	/* METHODS */
	/***********/

	void	DrawFormattedTextToScreen(CHAR16 * text, Rectangle area);


	/********************/ 
	/* MEMBER ACCESSORS */
	/********************/

	void	SetAlignment(TextAlignmentEnum alignment);
	TextAlignmentEnum GetAlignment(void);

	void	SetNormalFont(UINT32 font);
	UINT32	GetNormalFont(void);

	void	SetBoldFont(UINT32 font);
	UINT32	GetBoldFont(void);

	void	SetItalicFont(UINT32 font);
	UINT32	GetItalicFont(void);

	void	SetLineSpacing(UINT16 spacing);
	UINT16	GetLineSpacing(void);

	void	SetLineHeight(UINT16 height);
	UINT16	GetLineHeight(void);

private:

	/***************/
	/* DATA MEMBER */
	/***************/

	UINT32	NormalFont;			// font for normal text
	UINT32	BoldFont;			// font for bold-styled text
	UINT32	ItalicFont;			// font for italic-styled text; NOT YET IMPLEMENTED
	UINT16	LineSpacing;		// additional vertical distance between lines in pixels
	UINT16	LineHeight;			// height of one line in pixels
	TextAlignmentEnum Alignment;	// alignment of the contents


	/*************/
	/* CONSTANTS */
	/*************/

	static const CHAR16 WORD_DELIMITER = 32;	// Ascii-Code for word-delimiting char	
	static const CHAR16 TAG_START_CHAR = '[';	// first character of any formatting tag
	static const CHAR16 TAG_END_CHAR = ']';		// last character of any formatting tag


	/***********/
	/* METHODS */
	/***********/

	UINT16	GetLastCharacterOnLine(CHAR16 * text, UINT16 iStart, UINT16 maxLenght, UINT16 &lineLenght);
	void	DrawFormattedTextLineToScreen(CHAR16 * text, UINT16 iStart, UINT16 charCount, UINT16 locX, UINT16 locY);

	BOOL	TryMatchFormattingTag(CHAR16 * text, UINT16 iStart, CHAR16* tag, UINT16 &iResume);
	BOOL	IsBoldFontStartTag(CHAR16 * text, UINT16 iStart, UINT16 &iResume);
	BOOL	IsBoldFontEndTag(CHAR16 * text, UINT16 iStart, UINT16 &iResume);
	BOOL	IsNewLineTag(CHAR16 * text, UINT16 iStart, UINT16 &iResume);

};

#endif	// include guard


FormattedTextRenderer.cpp

 Code:
#ifdef PRECOMPILEDHEADERS
	#include "Laptop All.h"
#else
	#include "builddefines.h"
	#include <stdio.h>
	#include "laptop.h"
	//#include "files.h"
	//#include "Game clock.h"
	//#include "Utilities.h"
	//#include "WCheck.h"
	#include "Debug.h"
	#include "WordWrap.h"
	//#include "Render Dirty.h"
	//#include "Encrypted File.h"
	//#include "cursors.h"
	//#include "email.h"
	//#include "text.h"
#endif

#include "FormattedTextRenderer.h"


/********************/ 
/* MEMBER ACCESSORS */
/********************/

/******************************************************************************
	sets the private member 'Alignment'
*/
void FormattedTextRenderer::SetAlignment(FormattedTextRenderer::TextAlignmentEnum alignment)
{
	Alignment = alignment;
}

/******************************************************************************
	returns the value of the private member 'Alignment'
*/
FormattedTextRenderer::TextAlignmentEnum FormattedTextRenderer::GetAlignment(void)
{
	return Alignment;
}

/******************************************************************************
	sets the private member 'NormalFont'
*/
void FormattedTextRenderer::SetNormalFont(UINT32 font)
{
	NormalFont = font;
}

/******************************************************************************
	returns the value of the private member 'NormalFont'
*/
UINT32 FormattedTextRenderer::GetNormalFont(void)
{
	return NormalFont;
}

/******************************************************************************
	sets the private member 'BoldFont'
*/
void FormattedTextRenderer::SetBoldFont(UINT32 font)
{
	BoldFont = font;
}

/******************************************************************************
	returns the value of the private member 'BoldFont'
*/
UINT32 FormattedTextRenderer::GetBoldFont(void)
{
	return BoldFont;
}

/******************************************************************************
	sets the private member 'ItalicFont'

	REMARK: until Ja2 supports abitrary fonts, italic style will not be 
	implemented.
*/
void FormattedTextRenderer::SetItalicFont(UINT32 font)
{
	ItalicFont = font;
}

/******************************************************************************
	returns the value of the private member 'ItalicFont'
*/
UINT32 FormattedTextRenderer::GetItalicFont(void)
{
	return ItalicFont;
}

/******************************************************************************
	sets the private member 'LineSpacing'
*/
void FormattedTextRenderer::SetLineSpacing(UINT16 spacing)
{
	LineSpacing = spacing;
}

/******************************************************************************
	returns the value of the private member 'LineSpacing'
*/
UINT16 FormattedTextRenderer::GetLineSpacing(void)
{
	return LineSpacing;
}

/******************************************************************************
	sets the private member 'LineHeight'
*/
void FormattedTextRenderer::SetLineHeight(UINT16 height)
{
	LineHeight = height;
}

/******************************************************************************
	returns the value of the private member 'LineHeight'
*/
UINT16 FormattedTextRenderer::GetLineHeight(void)
{
	return LineHeight;
}

/****************/
/* CONSTRUCTORS */
/****************/

/******************************************************************************
	constructor; sets default values for non-static-constant members
*/
FormattedTextRenderer::FormattedTextRenderer(void)
{
	NormalFont = gp10PointArial;
	BoldFont = gp10PointArialBold;
	LineSpacing = 4;
	LineHeight = ( WFGetFontHeight(NormalFont) + LineSpacing );
	Alignment = Left;
}


/***********/
/* METHODS */
/***********/

/******************************************************************************
	
	private GetLastCharacterOnLine(...)

	returns the index of the last character in the passed string that fit onto
	a line of specified width

	CHAR16 * text	- the text that is to be investigated
	UINT16 iStart	- position of starting character for this line
	UINT16 maxLenght- maximum width of a line in pixels
	UINT16 &lineLenght - the lenght of the fitting text in pixels
*/
UINT16 FormattedTextRenderer::GetLastCharacterOnLine(CHAR16 * text, UINT16 iStart, UINT16 maxLenght, UINT16 &lineLenght)
{
	UINT16 iChar = iStart;			// loop-counter; position of currently investigated character

	UINT16 iLastWordDelimiter = 0;	// position of last word delimiter character
	UINT16 CurrentLineLenght = 0;	// lenght of current line in pixels
	UINT16 CurrentWordLenght = 0;	// lenght of current word in pixels
	CHAR16 CurrentChar[2];			// "array" holding a single char and a trailing null value
	CurrentChar[1] = L'\0';
	UINT16 CharWidth = 0;			// width of the current character in pixels

	UINT32 CurrentFont = NormalFont;// currently selected Font

	/* walk over all characters in array 'text' until null-value indicates 
		the end of the string */
	while ( text[iChar] != 0 )
	{

		switch( text[iChar] )
		{
		case TAG_START_CHAR:	// start character for formatting tag found
			{
				if( IsBoldFontStartTag(text, iChar, iChar) == TRUE )
				{
					// select bold font
					SetFont(BoldFont);
					CurrentFont = BoldFont;
				}
				else if( IsBoldFontEndTag(text, iChar, iChar) == TRUE )
				{
					// select normal font
					SetFont(NormalFont);
					CurrentFont = NormalFont;
				}
				else if( IsNewLineTag(text, iChar, iChar) == TRUE )
				{
					// since a NewLine tag was found the line ends here
					lineLenght = (CurrentLineLenght + CurrentWordLenght);
					return iChar;
				}
			}
		case WORD_DELIMITER:	// word delimiting character found
			{
				/* the position of the last word delimiter found is stored
					because if a character doesn't fit the line the non-complete
					word is wrapped onto the following line */

				iLastWordDelimiter = iChar;
			}
		default:	// some other character found
			{
				/* if this case is reached then a character that needs to be 
					printed is reached. Measure the width of it using the
					currently selected font and check whether it fits onto
					the line.

					if the character does not fit onto the line then all 
					characters until the last WORD_DELIMITER are put onto the
					following line */

				CurrentChar[0] = text[iChar];
				CharWidth = WFStringPixLength(CurrentChar, CurrentFont);
				CurrentWordLenght += CharWidth;

				/* check whether the word fits onto the line */
				if( (CurrentLineLenght + CurrentWordLenght) > maxLenght )
				{
					/* the word doesn' fit;
						check whether the line has any characters on it. 
						
						If the line does have at least one character on it then 
						discard the last (non-fitting) word.

						If the line has no characters on it then draw as many
						characters as possible. */

					if( CurrentLineLenght != 0 )
					{
						/* there are already characters on the line */
						lineLenght = CurrentLineLenght;
						return iLastWordDelimiter;
					}
					else
					{
						/* there are no characters on the line until now, that
							is we have one word that does not fit even a full
							line. 
							All but the last character until now are put onto
							this line */
						CurrentLineLenght = (CurrentWordLenght - CharWidth);
						lineLenght = CurrentLineLenght;
						return (iChar -1);
					}
				}
				else
				{
					/* the word does fit; check whether we are at a word 
						ending and append the CurrentWordLenght to the
						CurrentLineLenght */

					if( iChar == iLastWordDelimiter )
					{
						CurrentLineLenght += CurrentWordLenght;
						CurrentWordLenght = 0;
					}
				}
			}
		}

		// never foget to increment the char-counter!
		iChar++;
	}

	/* when we reached this point we have hit a null value indicating the end
		of the array. Just return the index of the last character and the 
		lenght of the text so far */
	lineLenght = (CurrentLineLenght + CurrentWordLenght);
	return iChar;
}

/******************************************************************************
	
	private DrawFormattedTextLineToScreen(...)

	draws a line of formatted text to the screen.

	CHAR16 * text	- the text that should be drawn
	UINT16 iStart	- the position of the first character
	UINT16 charCount- the number of characters to draw
	UINT16 locX		- vertical position of the first character in pixels
	UINT16 locY		- horizontal position of the first character in pixels
*/
void FormattedTextRenderer::DrawFormattedTextLineToScreen(CHAR16 * text, UINT16 iStart, UINT16 charCount, UINT16 locX, UINT16 locY)
{
	UINT16 iChar = 0;				// loop-counter; position of currently investigated character

	CHAR16 CurrentChar[2];			// "array" holding a single char and a trailing null value
	CurrentChar[1] = L'\0';
	UINT16 CharWidth = 0;			// width of the current character in pixels

	UINT32 CurrentFont = NormalFont;// currently selected font
	UINT8 CurrentColor = FONT_BLACK;// currently selected font color

	for( iChar = iStart; iChar < (iStart + charCount); iChar++)
	{
		
		/* if we hit a character that might form a formatting tag, check this!
			NOTE: if we have a formatting tag the value of iChar is altered
			in such a way that it points to the character after the tag-closing
			character! */
		if( text[iChar] == TAG_START_CHAR )
		{
			if( IsBoldFontStartTag(text, iChar, iChar) == TRUE )
			{
				// select bold font
				SetFont(BoldFont);
				CurrentFont = BoldFont;
			}			
			else if( IsBoldFontEndTag(text, iChar, iChar) == TRUE )
			{
				// select normal font
				SetFont(NormalFont);
				CurrentFont = NormalFont;
			}			
			else if( IsNewLineTag(text, iChar, iChar) == TRUE )
			{
				return;
			}
		}

		/* measure the width of the current character for clipping purposes */
		CurrentChar[0] = text[iChar];
		CharWidth = WFStringPixLength(CurrentChar, CurrentFont);

		/* draw text */
		DrawTextToScreen(CurrentChar, locX, locY, CharWidth, CurrentFont, CurrentColor, 0, FALSE, 0);	
		
		/* increase the vertical position by the width of the current character */
		locX += CharWidth;
	}
}

/*
	
	public DrawFormattedTextToScreen(...)

	draws the text given in the parameter 'text' into the screen area specified
	by 'area' to the screen.
	This method follows the class-property 'Alignment' and pays attention to
	the formatting tags in the text.

	CHAR16 * text	- the text that should be drawn
	Rectangle area	- the area to draw the text into
*/
void FormattedTextRenderer::DrawFormattedTextToScreen(CHAR16 * text, Rectangle area)
{
	UINT16 iStart = 0;		// position of first character on current line
	UINT16 iLast = 0;		// position of last character on current line
	UINT16 LineLenght = 0;	// lenght of current line in pixels
	UINT16 locY = area.Top;	// horizontal position of first character of current line
	UINT16 locX = 0;		// vertical position of first character of current line

	while ( text[iLast + 1] != 0 )
	{
		iStart = iLast;

		/* if the last character of the preceeding line was a WORD_DELIMITER
			then increment iStart by one to skip this WORD_DELIMITER because
			we don't want to have a line begin with a WORD_DELIMITER */
		if( text[iLast] == WORD_DELIMITER )
			iStart++;

		/* obtain the position of the last character to draw on this line */
		iLast = GetLastCharacterOnLine(text, iStart, area.Width, LineLenght);

		/* horizontal positioning depends on the selected text alignment */
		switch ( Alignment )
		{
		case Left:
			{
				/* left alignment of text */
				locX = area.Left;
				break;
			}
		case Right:
			{
				/* right alignment of text */
				locX = ( area.Left + (UINT16)((area.Width - LineLenght)*0.5) );
				break;
			}
		case Centered:
			{
				/* centered alignment of text */
				locX = ( area.Left + (area.Width - LineLenght) );
				break;
			}
		}
		
		/* draw the text */
		DrawFormattedTextLineToScreen(text, iStart, iLast - iStart, locX, locY);
		
		/* calculate the vertical position of the line 
			NOTE: we only allow fixed line height at the moment */
		locY += (LineHeight + LineSpacing);

		/* check whether our specified area can hold an other line.
			if it can not then exit the loop */
		if( locY > (area.Top + area.Height) )
			break;
	}
}

/******************************************************************************
	
	private TryMatchFormattingTag(...)

	compares a passed CHAR16 array 'text' with an other array 'tag' and 
	returns whether the two match.

	CHAR16 * text	- text to compare
	UINT16 iStart	- position to start comparision from
	CHAR16 * tag	- text to compare against; is evaluated from position 0.
	UINT16 &iResume - position to resume parsing at 
					  (first char after the tag if one is found)
*/
BOOL FormattedTextRenderer::TryMatchFormattingTag(CHAR16 * text, UINT16 iStart, CHAR16* tag, UINT16 &iResume)
{
	UINT16 iChar = 0;	// loop-counter
	
	/* the position to resume parsing at is set when a match is found, 
		otherwise all chars from iStart on are considered normal characters
		that should be printed normally. */
	iResume = iStart;
	
	/* walk over all characters in array 'text' until null-value indicates 
		the end of the string or the end of the formatting tag is reached */
	while ( text[iChar + iStart] != 0 )
	{
		/* check whether the end of the tag array is reached; if this is the  
			case then return FALSE because we should have left the method
			already in the previous loop circle if there were a match */
		if( tag[iChar] == 0 )
			return FALSE;

		/* compare tag and text chars; if these do not match then we
			return FALSE */
		if( tag[iChar] != text[iChar + iStart] )
			return FALSE;

		/* if a TAG_END_CHAR is reached and the method wasn't otherwise
			left then we have a match! */
		if( text[iChar + iStart] == TAG_END_CHAR )
		{
			iResume = (iStart + iChar + 1);
			return TRUE;
		}
		// never foget to increment the char-counter!
		iChar++;
	}

	/* the method should be left already so this point is unlikely to be 
		hit but we want to shut up the compiler warning C4715
		(The specified function can potentially not return a value.) */
	return FALSE;
}

/******************************************************************************
	
	private IsBoldFontStartTag(...)

	checks whether there is the FONT_BOLD_START tag at the passed position
	and returns TRUE or FALSE accordingly

	CHAR16 * text	- text to check
	UINT16 iStart	- suspected position
	UINT16 &iResume - position to resume parsing at 
					  (first char after the tag if one is found)
*/
BOOL FormattedTextRenderer::IsBoldFontStartTag(CHAR16 * text, UINT16 iStart, UINT16 &iResume)
{
	return TryMatchFormattingTag(text, iStart, L"[b]", iResume);
}

/******************************************************************************
	
	private IsBoldFontEndTag(...)

	checks whether there is the FONT_BOLD_END tag at the passed position
	and returns TRUE or FALSE accordingly

	CHAR16 * text	- text to check
	UINT16 iStart	- suspected position
	UINT16 &iResume - position to resume parsing at 
					  (first char after the tag if one is found)
*/
BOOL FormattedTextRenderer::IsBoldFontEndTag(CHAR16 * text, UINT16 iStart, UINT16 &iResume)
{
	return TryMatchFormattingTag(text, iStart, L"[/b]", iResume);
}

/******************************************************************************
	
	private IsNewLineTag(...)

	checks whether there is the NEW_LINE tag at the passed position
	and returns TRUE or FALSE accordingly

	CHAR16 * text	- text to check
	UINT16 iStart	- suspected position
	UINT16 &iResume - position to resume parsing at 
					  (first char after the tag if one is found)
*/
BOOL FormattedTextRenderer::IsNewLineTag(CHAR16 * text, UINT16 iStart, UINT16 &iResume)
{
	return TryMatchFormattingTag(text, iStart, L"[nl]", iResume);
}




I would really appreciate some feedback.

best regards
Arne
Offline - OFFLINE
Top
#181598 - 15 April, 2008 02:17 PM Re: Laptop files section [Re: lochkartenman]
Kaiden

Captain
Captain

Posts: 1832
I can definitely see a use for this once a scripting system has been developed.
_________________________
JA2 - 1.13 MOD [Coder]
Download it,Review it, and Rate it @ MOD DB
JA2 1.13 Wiki
NOT True is the new False.
Offline - OFFLINE
Top
Badges:
#181681 - 16 April, 2008 04:19 AM Re: Laptop files section [Re: Kaiden]
Will Gates

Captain
Captain

Posts: 1935
Loc: Far far away.
They made a bit of a mess with the files in any event. There are files called "files" in approx three different locations. Two are mostly blank; they just have one entry about Miguel and another about MoM. Only one is valid but I can't recall where it is kept; I'm too tired.



Edited by Will Gates (16 April, 2008 04:20 AM)
Edit Reason: must have smiley
_________________________
Klytus I'm bor-r-red; what plaything can you offer me today?

Offline - OFFLINE
Top
#181750 - 16 April, 2008 12:46 PM Re: Laptop files section [Re: Will Gates]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

I spend this evening fiddling around with the XML-code because I thought it might be the easier part compared with image loading & blitting.

Now I realized that most (if not all) XMLs are simple lists with one top item containing a set of identical structured subitems. There is no deeper nesting.
Problem is: if you dare to look into my first post you will clearly see that this does not hold true for the XML design of mine. That's a bit of a problem since I think such a "tree" with rather arbitrary sub nodes (PAGES and BOXES) is the most logical way of setting things up for the Laptop files.

The alternative would be introducing a set of say 2 or 3 XMLs - a step I would like to avoid.

By the way: is there a way to determine the number of subitems in a list? This would come in handy to allocate the array.

Please comment

regards
Offline - OFFLINE
Top
#181755 - 16 April, 2008 01:10 PM Re: Laptop files section [Re: lochkartenman]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

To circumvent the nesting of element collections I could imagine a set of XML files as follows:

LaptopFiles.xml: stores only the number of entries in subsidiary files to ease the array allocation
 Code:
<LAPTOPFILES>
	<FILE>
		<uiIndex>0</uiIndex>
		<uiPages>5</uiPages>
		<uiBoxes>25</uiBoxes>
		<uiTriggers>10</uiTriggers>
	</FILE>
	<FILE>
		<uiIndex>1</uiIndex>
		<uiPages>2</uiPages>
		<uiBoxes>25</uiBoxes>
		<uiTriggers>10</uiTriggers>
	</FILE>
</LAPTOPFILES>


LaptopFilesNames.xml: stores localized strings.
 Code:
<LAPTOPFILESNAME>
	<NAME>
		<uiFile>0</uiFile>
		<ubName>Recon report</ubName>
	</NAME>
	<NAME>
		<uiFile>1</uiFile>
		<ubName>Terrorists</ubName>	
	</NAME>
</LAPTOPFILESNAME>


LaptopFilesContents.xml: holds the localized texts & images and where to put these.
 Code:
<LAPTOPBOXES>
	<BOX>
		<uiFile>0</uiFile>
		<uiPage>0</uiPage>
		<uiLeft>25</uiLeft>
		<uiTop>25</uiTop>
		<uiHeight>150</uiHeight>
		<uiWidth>60</uiWidth>
		<uiType>0</uiType>
		<ubContents>This is some text</ubContents>
	</BOX>
	<BOX>
		<uiFile>0</uiFile>
		<uiPage>0</uiPage>
		<uiLeft>100</uiLeft>
		<uiTop>50</uiTop>
		<uiHeight>150</uiHeight>
		<uiWidth>60</uiWidth>
		<uiType>1</uiType>
		<ubContents>Image1.sti</ubContents>
	</BOX>
</LAPTOPBOXES>


The connection between the "master file" LaptopFiles.xml and the other files is the value of uiIndex (in LaptopFiles.xml) and uiFile (in all other files).

Triggers could probably done the same way. Or someone implements LUA-scripting..


This approach would "spread" the data out into more files but makes things easier to program. It might also be easier to tweak the XML-editor to work with these simpler files.

regards
Offline - OFFLINE
Top
#181760 - 16 April, 2008 02:55 PM Re: Laptop files section [Re: lochkartenman]
BirdFlu
Lieutenant
Lieutenant

Posts: 562
Loc: Lampukistan
 Quote:
By the way: is there a way to determine the number of subitems in a list? This would come in handy to allocate the array.

Just write the number into the file when you create it.

 Quote:
.. other xml stuff ..

Why are you dropping the nested xml files in favor of the flat xml files? Since you have to parse the files anyway, you can use any structure you like.

Since you are fiddling with graphics, have you read this thread?
http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=163777&page=1#Post163777
Offline - OFFLINE
Top
Badges:
#181872 - 17 April, 2008 08:21 AM Re: Laptop files section [Re: BirdFlu]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

@BirdFlu: Of course the nested xml is much "nicer" than a set of flat files because things that belong together should go into one file. My (personal) problem is that I am not too fluent with the C-style approach of writing code (lots and lots of #defines, flat code files, no classes..) and as such some aspects of the xml-parser code are still not entirely clear to me. Therefore the easier approach would be to simply copy'n'paste for example the XML_AmmoStrings file and rename things according to my purpose - not the most elegant way of doing things and probably also a bit opportunistic but even then it just works.

Yes, I followed the "Improving Original JA2 graphics – Sprites" thread quite carefully. I even had the hope that the whole idea would lead to overall streamlined graphics handling - which would hopefully make the rendering part of my project a lot easier. Unfortunately the discussion cooled down the last days and progress - code wise - is not to be expected in the near future, as far as I can tell.

While googling around and using the search function of this board quite excessively I stumbled over the "ja2-stracciatella" project. As I understood this port uses the SDL (Simple DirectMedia Layer
) library for drawing stuff. This would probably a huge improvement since at least there is a broad community and code base available. Could the current code be merged with ja2-stracciatella?

regards
Offline - OFFLINE
Top
#182210 - 19 April, 2008 08:07 AM Re: Laptop files section [Re: lochkartenman]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

Hi again.

I finally managed to read in a deeply nested xml. The question that rises is: should I adapt to the C-style currently used in the code base, that's one single .cpp-file with static methods, OR should I design some sort of class (probably singleton in this case). Both ways should work equally well and achieve exactly the same but are of different "philosophy".

regards
Arne
Offline - OFFLINE
Top
#182252 - 19 April, 2008 02:49 PM Re: Laptop files section [Re: lochkartenman]
Tron

Drill Sargeant
Drill Sergeant

Posts: 295
Loc: Germany
 Originally Posted By: lochkartenman
While googling around and using the search function of this board quite excessively I stumbled over the "ja2-stracciatella" project. As I understood this port uses the SDL (Simple DirectMedia Layer) library for drawing stuff. This would probably a huge improvement since at least there is a broad community and code base available. Could the current code be merged with ja2-stracciatella?


While I do not fully understand the part about "broad community and code base", I can tell you that SDL is mainly used for providing a frame buffer in JA2-Stracciatella. JA2 requires more specific blitting functions than SDL provides. I rewrote the JA2 blitters in C.
_________________________
Jagged Alliance 2 - Stracciatella - Bringing JA2 to SDL and everywhere
Offline - OFFLINE
Top
#182281 - 20 April, 2008 03:15 AM Re: Laptop files section [Re: Tron]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

@Tron: by "borad community and code base" I meant that for SDL there is a least some sort of documentation, tutorials and people to ask questions. Things that come in handy if you do not have much experience in graphics programming.

One question still remains: what "style" should I follow? Procedural C style OR C++ classes?

regards
Offline - OFFLINE
Top
#182288 - 20 April, 2008 05:17 AM Re: Laptop files section [Re: lochkartenman]
Tron

Drill Sargeant
Drill Sergeant

Posts: 295
Loc: Germany
From the perspective of game mechanics you do not encounter SDL functions (or any other system specific functions, for that matter) in JA2-Stracciatella, so this point is rather moot. On the other hand I have sanitised several in-game interfaces, which get used.
Here's a simple example:

original
 Code:
#define VOBJECT_CREATE_DEFAULT        0x00000020    // Creates and empty object of given width, height and BPP
#define VOBJECT_CREATE_FROMFILE       0x00000040    // Creates a video object from a file ( using HIMAGE )
#define VOBJECT_CREATE_FROMHIMAGE     0x00000080    // Creates a video object from a pre-loaded hImage
typedef struct
{
  UINT32        fCreateFlags;           // Specifies creation flags like from file or not
  union
  {
    struct
    {
      SGPFILENAME   ImageFile;              // Filename of image data to use
    };
    struct
    {
      HIMAGE        hImage;
    };
  };
  UINT8         ubBitDepth;             // BPP, ignored if given from file
} VOBJECT_DESC;
BOOLEAN AddStandardVideoObject( VOBJECT_DESC *VObjectDesc, UINT32 *uiIndex );
BOOLEAN GetVideoObject( HVOBJECT *hVObject, UINT32 uiIndex );
BOOLEAN BltVideoObject(  UINT32 uiDestVSurface, HVOBJECT hVSrcObject, UINT16 usRegionIndex, INT32  iDestX, INT32  iDestY, UINT32 fBltFlags, blt_fx *pBltFx );


now
 Code:
SGPVObject* AddStandardVideoObjectFromHImage(HIMAGE hImage);
SGPVObject* AddStandardVideoObjectFromFile(const char* ImageFile);
BOOLEAN BltVideoObject(SGPVSurface* dst, const SGPVObject* src, UINT16 usRegionIndex, INT32 iDestX, INT32 iDestY);


IMO it's pretty obvious, which of the two is easier to use, even disregarding that there was plain broken stuff (VOBJECT_CREATE_DEFAULT - where's width and height?) and unused parameters (pBltFx). Especially the cumbersome out-parameter-with-boolean-return is gone.
_________________________
Jagged Alliance 2 - Stracciatella - Bringing JA2 to SDL and everywhere
Offline - OFFLINE
Top
#182351 - 21 April, 2008 03:49 AM Re: Laptop files section [Re: Tron]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany

@Tron: How difficult could it be to merge your changes with the current v1.13 sources?
Offline - OFFLINE
Top
#182487 - 22 April, 2008 09:57 AM Re: Laptop files section [Re: lochkartenman]
Tron

Drill Sargeant
Drill Sergeant

Posts: 295
Loc: Germany
I'd rather do it the other way round: Add modifications to the JA2-Stracciatella source code. It's more than 140.000 lines shorter than the vanilla source code, several internal interfaces have been cleaned up, many bugs have been fixed (see Changelog), many brittle constructs have been replaced by more robust code to facilitate the detection of errors. Further it works not only on x86 Windows, but all 32bit little endian(*) platforms, for which SDL is available. Therefore I deem it more sensible to use JA2-Stracciatella as code base and add extensions there.


(*) removing the 32bit and little endian restrictions is still work in progress
_________________________
Jagged Alliance 2 - Stracciatella - Bringing JA2 to SDL and everywhere
Offline - OFFLINE
Top
#182531 - 22 April, 2008 01:23 PM Re: Laptop files section [Re: Tron]
lochkartenman
Merc
Merc

Posts: 63
Loc: Braunschweig, Germany
That sounds promising. I guess the sheer amount of work/time prevented the merge..

I managed to identify the patterns for buttons, displaying text and graphics files so far and although there is some "beauty" in some of these constructs I can hardly get used to it.

What I have achieved so far:
- reading nested XML into a structure
- display formatted text on the screen
- identify the interaction between laptop screens (work in progress)

I have a rather good feeling about the whole thing now. What I am a bit puzzled about is how the "new" files could be triggered. It would be quite a hassle to implement my own set of triggers in the form of XML-files (see first post) since there would be "one" missing trigger all the time.. plus if every single coder implements his/her own trigger system things are likely to become as messy as the "legacy" code.

So I would really appreciate if someone came up with some tips on how to design "LUA-ready" code since I suspect this to be the easiest and most flexible approach even if there is currently no one working on the matter.

regards
Offline - OFFLINE
Top



Forum Stats
7805 Members
52 Forums
7623 Topics
155493 Posts

Max Online: 228 @ 21 September, 2007 02:08 PM
Copyright 2000 Bear's Pit