Water ... that adapts itself to the flow, that breaks everything like a sword
RTTI: Changes for better
Get link
Facebook
X
Pinterest
Email
Other Apps
-
As some of you may know White Rabbit Engine use it's ownRun Time Type Information system. And well like with everything else sometimes come time when you need to upgrade stuff. Recently I had another occasion to do iteration over this system.
In this post I will try to give you a little bit insight how m RTTI look is engine, what changed and what are plans for future. But well let's start from begin.
Beginning
When I was designing own RTTI one of most important aspect was simplicity of use. When you adding RTTI to class it should be straight forward. Minimal amount of code you need to add and simple syntax. I think that in the end I achieve the goal but I won't say that it was like that right away. But well decide yourselves:
* Header
/*
==========================================================================
Some Rtti class
==========================================================================
*/
class CMyRttiClass : public CRttiObject
{
RTTI_CLASS(CMyRttiClass , CRttiObject);
public:
CMyRttiClass( void );
private:
wrStringID m_name;
CMeshResHandle m_meshResource;
void setResource( int32 a_idx );
};
* Source
// Includes
RTTI_DECLARATION_BEGIN(CMyRttiClass)
RTTI_ATTRIB(m_name)
.setAlias("Name")
.setEditorParams("[Unique]");
RTTI_ATTRIB(m_meshResource)
.setAlias("Mesh Resource")
.bindSetCallback(&CMyRttiClass ::setResource)
.setEditorParams("[Ext:'msh','mshxml']");
RTTI_DECLARATION_END
// Rest of code
...
Or use serialization of attributes that are added in declaration.
In above code all RTT_xyz are macros. They unwrap in meantime of compilation and sadly recently there was problem with parsing them by Visual Assist. It's intellisense stopped working in all my *.cpp with RTTI declarations which made me rally sad :(.
Occasion to changes for better
This was the moment for changes:] For some time I planed to switch part of RTTI on offline generated code. So I took my python project generator and added extra step. It parsing headers file in project where RTTI is enabled and generate from it "rtti_*.cpp" containing RTTI implementation .
* RttiGenerator.py
#!/usr/bin/python
import os
import re
#======================================================================
# This is RTTI code generator. It convert RTTI informations from class
# header to seperate generated *.cpp file.
#
# TEMPLATE FORMAT:
# Template file format is easy it's split on sections:
# [[SECTION_NAME]]
# Where you can select which part export by conditions:
# @if(conditionName)
# @else
# @endif
# And use variables (check : RttiGenerator.processTemplate(...))
#
# REMARKS:
# There is few advantages of this way of resolving RTTI code:
# * There is no issue with Visual Assist parsxing (yep there was issue
# when RTTI used macros)
# * You can step nicely into code with debugger.
# * Saving compilation time because generated code will end in separate
# object.
#======================================================================
class RttiGenerator:
def __init__(self, slnDir, rttiTemplatesDir, pch):
self.gen = None
self.slnDir = slnDir
self.pch = pch
self.templatePath = os.path.join( rttiTemplatesDir ,'template.rtti')
def processTemplate(template):
template = template.replace('{', '{{')
template = template.replace('}', '}}')
# Variables to use in template sctipt
template = template.replace('$(PCH)', '{pch}')
template = template.replace('$(CLASS)', '{classThis}')
template = template.replace('$(CLASS_BASE)', '{classBase}')
template = template.replace('$(FILE)', '{File}')
return template
def loadTemplate(self, path):
templateFile = open(path, 'r')
templateName = None
self.template = dict()
for line in templateFile:
line = RttiGenerator.processTemplate(line)
templateSectionRE = re.search('\[\[(\w+)\]\]', line)
if templateSectionRE != None:
templateName = templateSectionRE.group(1)
content = []
self.template[templateName] = content
elif templateName != None:
if line[0] == '@' or len(content) == 0:
content += [line, '']
else:
content[-1] += line
def getTemplate(self, section, conditions):
output = ''
stack = []
for line in self.template[section]:
conditionIf = re.match('@if\((.*)\)', line)
if conditionIf != None:
stack += [conditions[conditionIf.group(1)]]
continue
conditionElse = re.match('@else', line)
if conditionElse != None:
stack[-1] = not stack[-1]
continue
conditionEndif = re.match('@endif', line)
if conditionEndif != None:
stack = stack[0:len(stack)-1]
continue
if len(stack) == 0 or stack[-1] == True:
output += line
return output
def generate(self, path):
self.gen = None
pathRel = os.path.relpath(path, self.slnDir)
file = open(path, 'r')
conditions = dict()
conditions['Pch'] = self.pch != None
for line in file:
line = line.strip()
isInterface = False
searchRtti = re.match('RTTI\s*\(\s*(\w+)\s*\,\s*(\w+)\s*\)\s*[;]{0,1}', line)
if searchRtti == None:
searchRtti = re.match('RTTI_CLASS\s*\(\s*(\w+)\s*\,\s*(\w+)\s*\)\s*[;]{0,1}', line)
if searchRtti == None:
searchRtti = re.match('RTTI_INTERFACE\s*\(\s*(\w+)\s*\,\s*(\w+)\s*\)\s*[;]{0,1}', line)
isInterface = (searchRtti != None)
conditions['Interface'] = isInterface
if searchRtti != None:
classThis = searchRtti.group(1)
classBase = searchRtti.group(2)
if self.gen == None:
# Lazy loading of template file
self.loadTemplate(self.templatePath)
# Appending of formated header
fileHeader = self.getTemplate('HEADER', conditions)
self.gen = fileHeader.format(File=pathRel,
pch=self.pch,
classThis=classThis,
classBase=classBase)
# Appending of formated class header
classHeader = self.getTemplate('CLASS_HEADER', conditions)
self.gen += classHeader.format(File=pathRel,
pch=self.pch,
classThis=classThis,
classBase=classBase)
return self.gen
Above script is copy-paste from script I use. I think that comments in it tell most of the stuff about usage so I will skip duplicating it. So process works and allow me to do a lot more than before. There is only one issue: right now this step is done in meantime of project generation. So it not update when file change. Because of that I have already plan to include it in building process but well I will do it when I will find some time.
Even more nice changes
Other things I changed is style of casting. You probably don't remember it from above. I also had sometimes problems with remembering it's syntax :D So recently I decided to change it on something more intuitive :
This may not look like a big change but it's making stuff easier. Comfort of code writing is one of things we always need to take into account. If you think twice how to use something then it's mean that maybe something is wrong with it.
Plans for future
Right now except adding RTTI generation as building step I plan to move even more RTTI code from macros to generated *.cpp. There is also incoming revision of code :/ This maybe not be the funniest part but I want to check if all comments in it are still up to date and clarify few stuff there for behavior of system.
So like always start with problem description: I have some pool of command represented as enumerator. Each of command can have unique data that size can be different. I wanted to create system that allow me in easy way iterate over them and execute. After some time I created this implementation: template<ECommands::enum cmd> bool execCommandTemp(ECommands::ENUM a_cmd, void* a_data) { if (a_cmd == cmd) { SCommand<cmd>::execute((SCommand ::SData*)a_data); return false; } return execCommandTemp<(ECommands::ENUM)(cmd+1)>(a_cmd, a_data); } template<> bool execCommandTemp<ECommands::WRAP>(ECommands::ENUM a_cmd, void* a_data) { return true; } bool execCommand( ECommands::ENUM a_cmd, void* a_data ) { return execCommandTemp<(ECommands::ENUM)0>(a_cmd, a_data); } where SCommand look in example such a way: template <> st...
On begin I wold like to thanks two people: You Tube user rezoner1337 for publishing info about remake on wykop and gog.com forum user M2Grzegorczy for this topic . It's really great to see that they shown such a initiative and to say truth the moment I saw this posts I couldn't believe. So what else left for me thanks you again. Second thing is the problem I was pinpointed by few people: there is no easy way to communicate with me. So I added email contact on blog because alexfont wrote that he couldn't found any. Maybe any of you have other proposition how to make contact with me easier? And on end progress of game: this week I spend mostly on AI and removing sliding of player. I will not say to much here because I plan to show both things in next movie which will have this time music created specially for game by Jesse Gorter . From more interesting changes is shown of discrete mode with animation and influence on gameplay. So e...
W ostatnich miesiącach rozpocząłem pracę wiec trochę mniej czasu pozostało na programowanie. Jednak udaje mi się go trochę wygospodarować. I tak poza kursem CUDA który realizuję na uniwerku. Moim głównym zajęciem jest tworzenie WRE jest to mój silnik wyposażony dodatkowo w edytor. Póki co nie ma za bardzo co pokazywać bo głównie poświęcam się rzeczą mało widocznym ale systematycznie w miarę dorzucam nowe rzeczy. Ostatnimi czasy zajmowałem się trochę systemem materiałów który doczekał się w końcu dziedziczenia :] pomaga to wielce w tworzeniu nowych materiałów. Zmienił się również system OCtree który w razie potrzeby potrafi się już rozszerzyć (w stosunku do wejściowego obszaru). No i dość dynamicznie rozwija się również edytor. Jak widać na screenie jestem już w stanie stworzyć prostą scenę jednak jeszcze dość długa droga zanim będzie można w nim łatwo i wygodnie tworzyć lokacje gry.
Comments
Post a Comment