irrPreSetting

Announce new projects or updates of Irrlicht Engine related tools, games, and applications.
Also check the Wiki

irrPreSetting

Postby lug » Sat Nov 18, 2006 7:43 pm

Yeah, it's me again, lug. Here's a small program that allows you to select the screen resolution, fullscreen options, etc. sort of like the ogre config launcher except this one uses xml. It took me a day and a half to code it up and run some rudimentary tests -- I know, I'm slow. :D

I know this has probably been done a million times. But I like to share, okay? I'm learning vc++ and winforms programming. So, hopefully someone would find the code and tool useful. I found most of my answers by searching the irrlicht forum. You can find some excellent info on this forum.

Anyway, here's what it can currently do (usual stuff):

+ fullscreen option on/off
+ stencil buffer option on/off
+ vsync option on/off
+ display driver
+ screen resolution height
+ screen resolution weight
+ screen resolution bits
+ read in values from xml file
+ minimal error checking

I'm currently working on getting it to write to xml. Also, I'm going to add in more error checking code after I've completed the code to allow it to write to xml. I'm also planning a x64 and a .NET 3.0 version (vista only). But let's not get ahead of ourself, eh? :)

Here're some screen captures of the program (i'm running vista that's why the window looks so funky; also ignore the background -- man, that would be nice to have a grass node looking like that, eh? *lug nudges bitplane* :wink: ):

Image

Image

Image

Here's the xml file that the program uses:

Code: Select all

<!-- Pre Setting Configuration File -->

<Config>

<!-- Misc Options                   -->

<Fullscreen         value  = "False"    />
<Stencilbuffer      value  = "False"    />
<Vsync              value  = "False"    />

<!-- Display Options                -->

<DisplayDriver      type   = "Null Device" />
<ScreenResHeight    value  = "640"         />
<ScreenResWidth     value  = "480"         />
<ScreenResBits      value  = "8"           />
      
</Config>



This was developed using .NET 2.0 vc++ and winform. It uses the SVN non-.NET irrlicht dll which means it contains mixed managed and un-managed code.

I used the "/clr" switch instead of the "/clr:safe" or "/clr:pure" switch in order to take advantage of the non-.NET version of irrlicht. I can't seem to find the operation to get the mode list in the .NET version of irrlicht.

This is pretty much the main guts of the code since everything right now is done when the form first loads:

Code: Select all

   private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e)
          {             
             // instantiate a dummy irrlicht device
             IrrlichtDevice * device = createDevice(
                video::EDT_NULL,
                core::dimension2d<s32>(0,0),
                false,
                false);

             // query the device to obtain the available video mode
             IVideoModeList * availableVideoModeList = device->getVideoModeList();

             // define array to hold a formatted listing of the availabe modes
             wchar_t formated_listing[64] = L" ";

             // go through all available video mode for graphic adapter
             for(int i = 0; i < availableVideoModeList->getVideoModeCount(); ++i)
             {
                // format available modes into desired listing
                swprintf(
                   formated_listing,
                   64,
                   L"%i x %i pixels @ %i-bit colors",
                   availableVideoModeList->getVideoModeResolution(i).Width,
                   availableVideoModeList->getVideoModeResolution(i).Height,
                   availableVideoModeList->getVideoModeDepth(i));

                // convert wchar_t to string object
                 System::String^ mode_listing = gcnew System::String(formated_listing);

                // add formatted mode to combo list box
                cmbScreenResolution->Items->Add(mode_listing);
             }

             // load in values from xml file if one already exists
             io::IXMLReader * xml_file = device->getFileSystem()->createXMLReader("pre_settings.xml");

             // check if opened successfully or not (0)
             if(xml_file == 0)
             {
                // show popup saying file could not be found
                MessageBox::Show(
                   "Missing xml setting config file! Falling back to default settings",
                   "The file \"pre_settings.xml\" cannot be found.",
                         MessageBoxButtons::OK,
                   MessageBoxIcon::Exclamation);
             }

             // define arrays to hold a xml screen resolution values
             wchar_t formatted_height[64] = L" ";
             wchar_t formatted_width[64] = L" ";
             wchar_t formatted_bits[64] = L" ";

             // parse through the xml file
             while(xml_file && xml_file->read())
             {
                // current XML node
                switch(xml_file->getNodeType())
                {
                   // xml element
                   case io::EXN_ELEMENT:
                      // go through all the xml element in file and set
                      // the window controls as appropriate
                      if(!std::wcscmp(L"Fullscreen",xml_file->getNodeName()))
                      {
                         // default to safe value
                         cbFullScreen->Checked = false;

                         // value is true
                         if(!std::wcscmp(L"True",xml_file->getAttributeValue(L"value")))
                         {
                            // set control to checked
                            cbFullScreen->Checked = true;
                         }
                      }
                      else if(!std::wcscmp(L"Stencilbuffer",xml_file->getNodeName()))
                      {
                         // default to safe value
                         cbStencilBuffer->Checked = false;

                         // value is true
                         if(!std::wcscmp(L"True",xml_file->getAttributeValueSafe(L"value")))
                         {
                            // set control to checked
                            cbStencilBuffer->Checked = true;
                         }
                      }
                      else if(!std::wcscmp(L"Vsync",xml_file->getNodeName()))
                      {
                         // default to safe value
                         cbVsync->Checked = false;

                         // value is true
                         if(!std::wcscmp(L"True",xml_file->getAttributeValueSafe(L"value")))
                         {
                            // set control to checked
                            cbVsync->Checked = true;
                         }
                      }
                      else if(!std::wcscmp(L"DisplayDriver",xml_file->getNodeName()))
                      {
                         // look for "Null Device" index value in the list of drivers
                         int index = cmbDisplayDriver->FindString("Null Device");
                        
                         // set the combobox to show the found index to use as default driver
                         cmbDisplayDriver->SelectedIndex = index;

                         // read driver string from xml and set the correct index in combobox
                         if(!std::wcscmp(L"EDT_SOFTWARE",xml_file->getAttributeValueSafe(L"type")))
                         {
                            int index = cmbDisplayDriver->FindString("Software Renderer");
                            cmbDisplayDriver->SelectedIndex = index;
                         }
                         else
                          if(!std::wcscmp(L"EDT_SOFTWARE2",xml_file->getAttributeValueSafe(L"type")))
                         {
                            int index = cmbDisplayDriver->FindString("Apfelbaum Software Renderer");
                            cmbDisplayDriver->SelectedIndex = index;
                         }
                         else
                         if(!std::wcscmp(L"EDT_DIRECT3D8",xml_file->getAttributeValueSafe(L"type")))
                         {
                            int index = cmbDisplayDriver->FindString("Direct3D 8 Renderer");
                            cmbDisplayDriver->SelectedIndex = index;
                         }
                         else
                         if(!std::wcscmp(L"EDT_DIRECT3D9",xml_file->getAttributeValueSafe(L"type")))
                         {
                            int index = cmbDisplayDriver->FindString("Direct3D 9 Renderer");
                            cmbDisplayDriver->SelectedIndex = index;
                         }
                         else
                         if(!std::wcscmp(L"EDT_OPENGL",xml_file->getAttributeValueSafe(L"type")))
                         {
                            int index = cmbDisplayDriver->FindString("OpenGL Renderer");
                            cmbDisplayDriver->SelectedIndex = index;
                         }
                      }
                      else if(!std::wcscmp(L"ScreenResHeight",xml_file->getNodeName()))
                      {
                         // save off screen resolution xml height value
                         std::wcscpy(formatted_height,xml_file->getAttributeValueSafe(L"value"));
                      }
                      else if(!std::wcscmp(L"ScreenResWidth",xml_file->getNodeName()))
                      {
                         // save off screen resolution xml width value
                         std::wcscpy(formatted_width,xml_file->getAttributeValueSafe(L"value"));
                      }
                      else if(!std::wcscmp(L"ScreenResBits",xml_file->getNodeName()))
                      {
                         // save off screen resolution xml bits value
                         std::wcscpy(formatted_bits,xml_file->getAttributeValueSafe(L"value"));
                      }
                      break;

                   // xml element
                   case io::EXN_ELEMENT_END:
                      {
                         // define array to hold a formatted screen resolution of the availabe modes
                         wchar_t formatted_screenresolution[64] = L" ";

                         // format available modes into desired listing
                         swprintf(
                            formatted_screenresolution,
                            64,
                            L"%s x %s pixels @ %s-bit colors",
                            formatted_height,
                            formatted_width,
                            formatted_bits);

                         // convert wchar_t to string object
                         System::String^ screen_res_xml_value = gcnew System::String(formatted_screenresolution);

                         // look for xml string in the list of drivers
                         int index = cmbScreenResolution->FindString(screen_res_xml_value);

                         // cannot find xml resolution in list of resolution index
                         if(index == -1)
                         {
                            // show popup saying unable to locate resolution in index
                            MessageBox::Show(
                               "No matching screen resolution found! Falling back to default settings",
                               "XML value for screen resolution cannot be found.",
                               MessageBoxButtons::OK,
                               MessageBoxIcon::Exclamation);

                            // set the combobox to show 1st resolution
                            cmbScreenResolution->SelectedIndex = 0;
                         }
                         // found xml resolution in list of resolution index
                         else
                         {
                            // set the combobox to show the found index to use as default driver
                             cmbScreenResolution->SelectedIndex = index;
                         }
                      }
                   break;
                    
                   default:
                   break;
                }
             }
          }


Anyway, I'll put the binary up once I find a good site to upload it to.

Update:

Download from here (uses rar; 557 KB):

http://www.megaupload.com/?d=JOBDDW2P

The buttons aren't working yet (close app using the "x" in the upper right of the program window), so you can try changing the xml file and see it load the values. It requires the .net 2.0 runtime. You can download it from here:

http://www.microsoft.com/downloads/deta ... laylang=en

Bye for now. :)
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby lug » Sun Nov 19, 2006 1:53 am

Here's code for the "Apply" button:

Code: Select all
private: System::Void bApply_Click(System::Object^  sender, System::EventArgs^  e)
       {
          // check to see if the file already exists
          if(!device->getFileSystem()->existFile("pre_settings.xml"))
          {
             // show popup saying file could not be found
             MessageBox::Show(
                "Cannot find xml setting config file! Creating a new file with default settings",
                "The file \"pre_settings.xml\" cannot be found.",
                MessageBoxButtons::OK,
                MessageBoxIcon::Exclamation);

             // define xml writer
             io::IXMLWriter * xml_write_file = device->getFileSystem()->createXMLWriter("pre_settings.xml");

             // write default values to xml file
             xml_write_file->writeComment(L" Pre Setting Configuration File ");
             xml_write_file->writeLineBreak();
             xml_write_file->writeElement(L"Config");
             xml_write_file->writeLineBreak();
             xml_write_file->writeComment(L" Misc Options                   ");
             xml_write_file->writeLineBreak();
             xml_write_file->writeElement(L"Fullscreen        ",true,L"value  ",L"False");
             xml_write_file->writeElement(L"Stencilbuffer     ",true,L"value  ",L"False");
             xml_write_file->writeElement(L"Vsync             ",true,L"value  ",L"False");
             xml_write_file->writeLineBreak();
             xml_write_file->writeComment(L" Display Options                ");
             xml_write_file->writeLineBreak();
             xml_write_file->writeElement(L"DisplayDriver     ",true,L"type   ",L"Null Device");
             xml_write_file->writeElement(L"ScreenResHeight   ",true,L"value  ",L"640");
             xml_write_file->writeElement(L"ScreenResWidth    ",true,L"value  ",L"480");
             xml_write_file->writeElement(L"ScreenResBits     ",true,L"value  ",L"8");
             xml_write_file->writeLineBreak();
             xml_write_file->writeClosingTag(L"Config");

             // cleanup
             xml_write_file->drop();
          }
          else
          {
             // define arrays to hold a xml screen resolution values
             wchar_t formatted_fullscreen[64] = L" ";
             wchar_t formatted_stencilbuffer[64] = L" ";
             wchar_t formatted_vsync[64] = L" ";

             // retrieve current value from form control
             if(cbFullScreen->Checked)
             {
                // save off value to set
                std::wcscpy(formatted_fullscreen,L"True");
             }
             else
             {
                // save off value to set
                std::wcscpy(formatted_fullscreen,L"False");
             }

             // retrieve current value from form control
             if(cbStencilBuffer->Checked)
             {
                // save off value to set
                std::wcscpy(formatted_stencilbuffer,L"True");
             }
             else
             {
                // save off value to set
                std::wcscpy(formatted_stencilbuffer,L"False");
             }

             // retrieve current value from form control
             if(cbVsync->Checked)
             {
                // save off value to set
                std::wcscpy(formatted_vsync,L"True");
             }
             else
             {
                // save off value to set
                std::wcscpy(formatted_vsync,L"False");
             }

             // obtain string from the winform control
             String^ temp_string = cmbScreenResolution->SelectedItem->ToString();

             // store trimmed strings after parsing
             String^ trimmed_height = gcnew String(" ");
             String^ trimmed_width = gcnew String(" ");
             String^ trimmed_bits = gcnew String(" ");

             // do clean token that contains the height value
             Regex^ h_regex = gcnew Regex("x");
             array<String^>^ h_token = h_regex->Split(temp_string);
             trimmed_height = h_token[0]->Trim();

             // do clean token that contains the width value
             Regex^ w_regex = gcnew Regex(" ");
             array<String^>^ w_token = w_regex->Split(h_token[1]);
             trimmed_width = w_token[1]->Trim();

             // isolate the "x-bit" string like in "8-bit"
             Regex^ b_regex = gcnew Regex(" ");
             array<String^>^ b_token = b_regex->Split(h_token[2]);

             // isolate the number before the "-" like in "8-bit"
             Regex^ b2_regex = gcnew Regex("-");
             array<String^>^ b2_token = b2_regex->Split(b_token[2]);
             trimmed_bits = b2_token[0]->Trim();

             // convert String^ object to wchar_t
             pin_ptr<const wchar_t> wch_scr_res_height = PtrToStringChars(trimmed_height);
             pin_ptr<const wchar_t> wch_scr_res_width = PtrToStringChars(trimmed_width);
             pin_ptr<const wchar_t> wch_scr_res_bits = PtrToStringChars(trimmed_bits);
             pin_ptr<const wchar_t> wch_dis_driv = PtrToStringChars(cmbDisplayDriver->SelectedItem->ToString());

             // define xml writer
             io::IXMLWriter * xml_write_file = device->getFileSystem()->createXMLWriter("pre_settings.xml");

             // write default values to xml file
             xml_write_file->writeComment(L" Pre Setting Configuration File ");
             xml_write_file->writeLineBreak();
             xml_write_file->writeElement(L"Config");
             xml_write_file->writeLineBreak();
             xml_write_file->writeComment(L" Misc Options                   ");
             xml_write_file->writeLineBreak();
             xml_write_file->writeElement(L"Fullscreen        ",true,L"value  ",formatted_fullscreen);
             xml_write_file->writeElement(L"Stencilbuffer     ",true,L"value  ",formatted_stencilbuffer);
             xml_write_file->writeElement(L"Vsync             ",true,L"value  ",formatted_vsync);
             xml_write_file->writeLineBreak();
             xml_write_file->writeComment(L" Display Options                ");
             xml_write_file->writeLineBreak();
             xml_write_file->writeElement(L"DisplayDriver     ",true,L"type   ",wch_dis_driv);
             xml_write_file->writeElement(L"ScreenResHeight   ",true,L"value  ",wch_scr_res_height);
             xml_write_file->writeElement(L"ScreenResWidth    ",true,L"value  ",wch_scr_res_width);
             xml_write_file->writeElement(L"ScreenResBits     ",true,L"value  ",wch_scr_res_bits);
             xml_write_file->writeLineBreak();
             xml_write_file->writeClosingTag(L"Config");

             // cleanup
             xml_write_file->drop();
          }
       }


I thought about using the boost library to do the string parsing but then I read the installation on their website. Too much work in my opinion just to bring in a library. It may be more elegant and safer than what I put together, but I'll save it for later. I just want something up and functional right now. Optimizing and stuff can come later. :)

Some points of interest about the above code:

1. For some reason, the xml generated by the IXMLWriter has a bug in it or something. Specifically, the writeLineBreak() call. This does not create a newline in the file for some reason thus making the generated xml file look horrible (viewing using notepad here).

2. Also related to the above, I can't seem to find a way to partially update an xml value for an existing xml file without wiping it out then created everything over again with the new values. Anyone know? I was thinking that maybe one needs to use IXMLWriter alongside IXMLReader but both constructer takes in the path of the xml file. How can they work in harmoney? If I construct an IXMLWriter it purges the xml file clean. :shock:

3. Yes, the string parsing could use some work but it's functional as is. It's a brute force method no doubt about it.

4. The code is messy. I definitely can move some stuff into member functions to unclutter it up a bit.

This "tiny" program has gotten me thinking a lot. Since a user can do all sort of thinks, it's difficult and tedious to "think" what a user would do then anticipate it in code. I've used messagebox to display errors like when a file is not found and such. But what if the user deletes the xml file while the program is running? :!:

I took this scenario into consideration with the apply button code above. Basically, the program will generate a new xml file using the current values in the winform controls at the time of pushing the apply button. I just now realize that if the user somehow makes the combobox/dropdown box field empty, the program will write blank value for the screen resolution. :(

Anyway, it's turning out to be a pretty big task (but very educational). I'll going to try to fix the above and add a way to tell when new changes has occurred. So that when you click the apply button, I'll gray it out if the user hasn't made any new changes/options. If they do, I enable the apply button again. I guess I could also add an "*" to the title bar to denote that a change has occur that hasn't been written/saved to the xml file.
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby a_haouchar » Sun Nov 19, 2006 2:21 am

actually i really like it and only took a day and a half,very good :o
a_haouchar
 
Posts: 97
Joined: Sat Oct 14, 2006 10:51 am
Location: Australia,melbourne

Postby hybrid » Sun Nov 19, 2006 12:49 pm

Would be nice to have all this in Irrlicht GUI elements using, e.g., the software renderer. This would pretty much simplify everyone's work (not only of those using .net 3). Using the null device to probe the resolutions and then the software devices to render on all platforms should be pretty straightforward.
hybrid
Admin
 
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Postby lug » Sun Nov 19, 2006 4:17 pm

a_haouchar -- thanks!

hybrid -- oh, hi there! I thought about doing it like that at first but I wanted to practice with using winforms and vc++ .net. I'll make a version like you suggested after I get the winform version at a stable state. Which is pretty darn close now. Maybe another half day or so, I'll have it completed. I actually use the null device in the winforms version if you look at the first code post. I can see how the non-winforms version would be more useable since you don't need 3d graphic card or any .net runtime. Thanks!

I've fixed the problem with the IXMLWriter not writing newline by just switching over to tinyxml. I had trouble getting tinyxml to compile but then found help from an ogre forum post. Basically, it needed to be built as a static lib then linked into the project. It also looks like no one is updating the tinyxml project. Anyway, I tried the write tutorial out and it worked like a charm.

Also, I found a way to keep the user from entering in text in the combobox/dropdown. It's so simple it hurts. Basically, you change the control DropDownStyle to DropDownList instead of the default DropDown. Not a single line of code added (well, at least not by yourself, the winform designer auto adds it for you).
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby hybrid » Sun Nov 19, 2006 5:24 pm

Ah, glad to hear of the planned 'pure Irrlicht' version :D
Why do you want to pretty print the XML code? It should work, indeed, but without linebreaks it is even faster to parse :wink:
hybrid
Admin
 
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Postby bitplane » Sun Nov 19, 2006 9:24 pm

svn irrlicht almost has the linebreak problem fixed, it still doesn't write line-breaks properly as part of a value though.
just #include "IrrCompileConfig.h" at the top of CXMLWriter.cpp and replace the following function:
Code: Select all
//! Writes a line break
void CXMLWriter::writeLineBreak()
{
   if (!File)
      return;

#if (defined(LINUX) || defined(MACOSX))

   File->write(L"\x000A", 2);

#elif (defined(_IRR_WINDOWS_) || defined(_XBOX))

   File->write(L"\x000D\x000A", 4);
#else
   File->write(L"\n", 2);
#endif

}
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
User avatar
bitplane
Admin
 
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England

Postby lug » Sun Nov 19, 2006 10:42 pm

hybrid -- mainly so that if user wants to directly edit the xml file they can without seeing one long line without line break. It makes it easier to read on the eye. :)

bitplane -- thanks a lot! I started switching out my IXMLWriter calls with tinyXML. But then after wrestling with using tinyXML, I gave up and found an example on the web. Now, when I just understand what to do to make it work for my stuff, you've presented a much better route. :) Why didn't I think of that? I've been using the 276 SVN version. I just did an SVN pulled just a second ago (SVN is at 310 now). And took a look at the CXMLWriter.cpp file. I don't really understand why the 276 version of writeLineBreak() using the following code did not work:

File->write("\n", 2);

I guess it has to do with wide character "L" and those "x000D\x000A" thingy? Is that the hex value for carriage return and newline?

Anyway, I'll try it out. It's a good thing I have not deleted the old IXMLWriter code yet. Now that would've been a pisser. :shock:

Update:

Okay, after some googling, I've answered my own question. I can barely make it out on a korean website, but it says:

(carriage return: &#x000D;)
(line feed: &#x000A;)

I've tried it with a win32 console program using cout and it does add a newline:

cout << "start newline test\x000D\x000A" << endl;
cout << "bitplane is cool" << endl;

Now, I just need to re-build irrlicht with the fix. :)
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby lug » Mon Nov 20, 2006 12:51 am

Well, changing CXMLWriter.cpp to use this:

File->write(L"\x000D\x000A", 4);

Now works for the most part. See pic below (left is the desired formatting; right is the one written with the "fix"):

Image

Note the addition of the indentation in the one on the right. Also, in order to make it look like the above one on the right, I had to make many calls to writeline():

Code: Select all
                 // define xml writer
                 io::IXMLWriter * xml_write_file = device->getFileSystem()->createXMLWriter("pre_settings.xml");

                 // write default values to xml file
                 xml_write_file->writeComment(L" Pre Setting Configuration File ");
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"Config");
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeComment(L" Misc Options                   ");
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"Fullscreen        ",true,L"value  ",formatted_fullscreen);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"Stencilbuffer     ",true,L"value  ",formatted_stencilbuffer);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"Vsync             ",true,L"value  ",formatted_vsync);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeComment(L" Display Options                ");
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"DisplayDriver     ",true,L"type   ",wch_dis_driv);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"ScreenResHeight   ",true,L"value  ",wch_scr_res_height);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"ScreenResWidth    ",true,L"value  ",wch_scr_res_width);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeElement(L"ScreenResBits     ",true,L"value  ",wch_scr_res_bits);
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeLineBreak();
                 xml_write_file->writeClosingTag(L"Config");

                 // cleanup
                 xml_write_file->drop();


Maybe a suggestion is to add a parameter to specfy how many line break/new line to insert like below (to insert 2 lines):

Code: Select all
xml_write_file->writeLineBreak(2);


Also, it would be nice to allow the user to specify if he/she wishes to indent or not maybe in the form of a property like so:

Code: Select all
xml_write_file->disableIndentation(true);


or better yet add a second parameter to specify indentation:

Code: Select all
                 xml_write_file->writeClosingTag(L"Config",0);


The "0" means no indentation while other values means to indent that many spaces. What do you think?
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby lug » Mon Nov 20, 2006 4:16 am

More IXMLWriter woes. After my last post, every time I write a new xml file. The program would stop loading the xml values on startup. I did some debugging and found that the values returned from "getAttributeValueSafe()" were blanks. Huh? :?

So, I did a diff between the two files and found no difference. I've found that if I change a value in the file then save, it would work. But if I ever write a new file, it wouldn't work. It only works if I hand modify the xml file. Strange. So, I decided to see what's underneath the file by doing a hex diff between the two files. This is what it shows:

Image

The right side of the pic shows the one that I hand changed (the working one). Notice the "FF FE" at the beginning of the file. If I use the IXMLWriter to write the XML file, I get the one on the left without the "FF FE" which my program see blanks. :evil:

Can anyone wager a guess as to what the "FF FE" means and why does my program like that over the non-"FF FE" file? This XML stuff is much more difficult than I originally thought. :cry:

Update:

Google came through once more:

Initial FF FE is a signature indicating the rest of the text is little endian UTF-16.


Update 2:

It's called byte order mark:

http://en.wikipedia.org/wiki/Byte_Order_Mark

So, a suggestion would be for the xml reader to check for these bytes then use the appropriate version of the xml reader (utf-8, utf-16, utf-32, etc.) automatically. This would shield issues like this from the dev/user.
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby bitplane » Mon Nov 20, 2006 10:25 am

hmm yes it should, and the writer should write the marker to the file too.
one thing worth mentioning is that valid xml files should have one root tag, and they should have the header too-
Code: Select all
<?xml version="1.0"?>
<only_one_root_tag>
  <my_data_here/>
</only_one_root_tag>

I can't test here at work, do you get the same problems when using a standard xml file like the one above?
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
User avatar
bitplane
Admin
 
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England

Postby jam » Mon Nov 20, 2006 10:59 am

If I remember correctly, when I played around with the XML features of Irrlicht. If you did not use the writeXMLHeader function when you saved the file, then when you read the file it would have read errors much like you describe. I don't know if this is the problem, but I thought I toss my 2 cents in.
system-independent, adj.:
Works equally poorly on all systems.
-- unknown
jam
 
Posts: 409
Joined: Fri Nov 04, 2005 3:52 am

Postby hybrid » Mon Nov 20, 2006 12:35 pm

Yes, both things are written by CXMLWriter::writeXMLHeader(). Add this to your write procedue and it should work as expected.
BTW (this seems to be going quite offtopic on irrXML): I think that the whole XMLWriter stuff won't work with big endian systems, since all wchar_t sizes are assumed to be 16bit (which they aren't) and thus the second 16bit are lost. I think these are the relevant ones on big endian systems. My changes in one of the last revisions of Irrlicht SVN will thus break the writer since I put in sizeof(wchar_t) at some points. I'll revert this now and think about a correct implementation...
hybrid
Admin
 
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Postby lug » Mon Nov 20, 2006 4:45 pm

jam wrote:If I remember correctly, when I played around with the XML features of Irrlicht. If you did not use the writeXMLHeader function when you saved the file, then when you read the file it would have read errors much like you describe. I don't know if this is the problem, but I thought I toss my 2 cents in.


That did it. It wrote the header and added the "FF FE" at the start of the file. :) Well, gee. I guess one has to write the xml header in order for the xml reader to work correctly. I was going against the xml standard it seems. But it would be nice to know about this "feature" in the irrxmlreader doc. An entry like this:

"Don't be a dummy like, lug. If you want to properly read xml file you write with XMLWriter, you must write a header first!"

:lol:

I did see where it checks for the different utf types in the xml reader code after my last post, but went to bed 'cause it was like 2 am or so -- lug exhausted.

Thanks guys. Some more testing and this baby is ready to be posted for everyone to download and try. Then I'm off to make the "pure" irrlicht version like how hybrid puts it. :)
lug
 
Posts: 79
Joined: Tue May 02, 2006 5:15 am

Postby RapchikProgrammer » Mon Nov 20, 2006 5:17 pm

This is really nice, i personally think this shud be integrated into irrlicht and there shud be an optional call to start either with the presetting or do settings manually!
User avatar
RapchikProgrammer
 
Posts: 279
Joined: Fri Dec 24, 2004 6:37 pm

Next

Return to Project Announcements

Who is online

Users browsing this forum: No registered users and 1 guest