00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "PShaderTxt.h"
00022
00023 #include <qlayout.h>
00024 #include <qmessagebox.h>
00025 #include <iostream>
00026 #include <sstream>
00027 #include <fstream>
00028 #include <stateGlift.h>
00029
00030 using namespace std;
00031 using namespace glift;
00032
00033 PShaderTxt::PShaderTxt(const QGLContext *ctx, QWidget *parent, const char *name, WFlags wf)
00034 : QWidget(parent, name, wf),
00035 _stype(NOT_LOADED),
00036 _shader(0),
00037 _fpshader(0),
00038 _vpshader(0),
00039 _ctx(ctx),
00040 _errw(0)
00041 {
00042 QHBoxLayout *topLayout = new QHBoxLayout( this, 2 );
00043
00044 _mle = new QMultiLineEdit( this, "shader text editor" );
00045 topLayout->addWidget(_mle);
00046 _mle->setWordWrap( QMultiLineEdit::WidgetWidth );
00047 _mle->setText("");
00048 _errw = new ErrTxtWin("",0,"a text error window");
00049 _errw->resize(512,768);
00050 _errw->setCaption("Programmable Shader Error");
00051 }
00052
00053 PShaderTxt::~PShaderTxt()
00054 {
00055
00056 }
00057
00058
00059
00060
00061 QString PShaderTxt::getFileName()
00062 {
00063 if(_shader.isNull())
00064 return QString("No Shader");
00065
00066 switch(_stype) {
00067 case ARB_FP:
00068 if(_fpshader->getProgFile())
00069 return QString(_fpshader->getProgFile());
00070 else
00071 break;
00072 case ARB_VP:
00073 if(_fpshader->getProgFile())
00074 return QString(_fpshader->getProgFile());
00075 break;
00076 }
00077
00078 return QString("Not Saved");
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 void PShaderTxt::loadShader()
00092 {
00093
00094 int errpos = -1;
00095 string fperr;
00096 ostringstream oss;
00097 ostream *ossave;
00098
00099
00100
00101 const_cast<QGLContext*>(_ctx)->makeCurrent();
00102
00103
00104 switch(_stype)
00105 {
00106 case ARB_FP:
00107
00108 ossave = _fpshader->getErrStream();
00109
00110 _fpshader->setErrStream(&oss);
00111
00112 _fpshader->reload(_mle->text().ascii());
00113
00114 _fpshader->setErrStream(ossave);
00115
00116 fperr = oss.str();
00117
00118 _errw->maybeError(fperr.c_str());
00119
00120 if( (errpos = getErrorPos(fperr)) > -1 )
00121 {
00122 _errw->markSelection(errpos);
00123 }
00124
00125 break;
00126 case ARB_VP:
00127
00128 ossave = _vpshader->getErrStream();
00129
00130 _vpshader->setErrStream(&oss);
00131 _vpshader->reload(_mle->text().ascii());
00132 _vpshader->setErrStream(ossave);
00133 fperr = oss.str();
00134
00135 _errw->maybeError(fperr.c_str());
00136 if( (errpos = getErrorPos(fperr)) > -1 )
00137 {
00138 _errw->markSelection(errpos);
00139 }
00140
00141 break;
00142
00143 }
00144 }
00145
00146
00147
00148
00149 void PShaderTxt::loadShader(glift::ProgShaderSP shader)
00150 {
00151 if((_stype != NOT_LOADED) || (!_shader.isNull()))
00152 {
00153 cerr << "PShaderTxt::loadShader(), Shader already loaded!!!" << endl;
00154 return;
00155 }
00156
00157 if(shader.isNull())
00158 {
00159 cerr << "PShaderTxt::loadShader(), Shader is null!!!" << endl;
00160 return;
00161 }
00162
00163 _shader = shader;
00164 if(castShader())
00165 {
00166 cerr << "PShaderTxt::loadShader(), Shader type not supported" << endl;
00167 return;
00168 }
00169
00170
00171 switch(_stype){
00172 case ARB_FP:
00173 _mle->setText(QString(_fpshader->getProgText()));
00174 break;
00175 case ARB_VP:
00176 _mle->setText(QString(_vpshader->getProgText()));
00177 break;
00178 }
00179
00180 loadShader();
00181 }
00182
00183
00184
00185
00186
00187 void PShaderTxt::loadShaderFromFile(const QString &fname)
00188 {
00189 if((_stype != NOT_LOADED) || (!_shader.isNull()))
00190 {
00191 cerr << "PShaderTxt::loadShaderFromFile(), Shader already loaded!!!" << endl;
00192 return;
00193 }
00194
00195 if(fname.isEmpty())
00196 {
00197 cerr << "PShaderTxt::loadShaderFromFile(), No file name given" << endl;
00198 return;
00199 }
00200
00201
00202 if((!_ctx) || (!_ctx->isValid()))
00203 {
00204 cerr << "PShaderTxt::loadShaderFromFile(), Invalid gl context" << endl;
00205 return;
00206 }
00207
00208
00209 const_cast<QGLContext*>(_ctx)->makeCurrent();
00210
00211
00212 ostringstream oss;
00213
00214 _shader = glift::getProgShaderFromFile(fname, (ostream*)&oss);
00215
00216 _errw->launchError(oss.str().c_str());
00217
00218 int errpos = -1;
00219 if( (errpos = getErrorPos(oss.str())) > -1 )
00220 {
00221 _errw->markSelection(errpos);
00222 }
00223
00224
00225 if(castShader())
00226 {
00227 cerr << "PShaderTxt::loadShaderFromFile(), shader type not supported" << endl;
00228 }
00229
00230
00231 switch(_stype){
00232 case ARB_FP:
00233 _mle->setText(QString(_fpshader->getProgText()));
00234 break;
00235 case ARB_VP:
00236 _mle->setText(QString(_vpshader->getProgText()));
00237 break;
00238 }
00239 }
00240
00241
00242
00243
00244 void PShaderTxt::loadShaderFromText(const QString &text)
00245 {
00246 if((_stype != NOT_LOADED) || (!_shader.isNull()))
00247 {
00248 cerr << "PShaderTxt::loadShaderFromText(), Shader already loaded!!!" << endl;
00249 return;
00250 }
00251
00252 if(text.isEmpty())
00253 {
00254 cerr << "PShaderTxt::loadShaderFromText(), No Shader to load" << endl;
00255 return;
00256 }
00257
00258
00259 const_cast<QGLContext*>(_ctx)->makeCurrent();
00260
00261
00262 ostringstream oss;
00263
00264 _shader = glift::getProgShaderFromText(text, (ostream*)&oss);
00265
00266 _errw->launchError(oss.str().c_str());
00267
00268 int errpos = -1;
00269 if( (errpos = getErrorPos(oss.str())) > -1 )
00270 {
00271 _errw->markSelection(errpos);
00272 }
00273
00274
00275 if(castShader())
00276 {
00277 cerr << "PShaderTxt::loadShaderFromFile(), shader type not supported" << endl;
00278 }
00279
00280
00281 _mle->setText(text);
00282 }
00283
00284
00285
00286
00287
00288 void PShaderTxt::saveShader(const QString &lastPath)
00289 {
00290 QString s;
00291 ofstream of;
00292
00293 if(_mle->isModified())
00294 loadShader();
00295
00296 switch(_stype)
00297 {
00298 case ARB_FP:
00299 if(_fpshader.isNull())
00300 {
00301 cerr << "PShaderTxt::saveShader(), null fpshader" << endl;
00302 return;
00303 }
00304
00305
00306 if(!_fpshader->getProgText()) return;
00307
00308
00309 if(!_fpshader->getProgFile())
00310 {
00311 s = QFileDialog::getSaveFileName( lastPath, "Shaders (*.fp *.txt)");
00312 if(QString::null == s)
00313 return;
00314 _fpshader->setProgFile(s.ascii());
00315 }
00316 else
00317 {
00318 s = _fpshader->getProgFile();
00319 }
00320 of.open(s.ascii(), ios::binary);
00321 if(of.bad())
00322 {
00323 _errw->launchError( "failed to open " + s + " for writing \n" );
00324 of.close();
00325 return;
00326 }
00327
00328 of.write(_fpshader->getProgText(), strlen(_fpshader->getProgText()));
00329
00330 if(of.bad())
00331 {
00332 _errw->launchError( "error writing " + s + "\n" );
00333 of.close();
00334 return;
00335 }
00336
00337 of.close();
00338 _mle->setModified(false);
00339 return;
00340
00341 break;
00342 case ARB_VP:
00343 if(_vpshader.isNull())
00344 {
00345 cerr << "PShaderTxt::saveShader(), null vpshader" << endl;
00346 return;
00347 }
00348
00349 if(!_vpshader->getProgText()) return;
00350
00351
00352 if(!_vpshader->getProgFile())
00353 {
00354 s = QFileDialog::getSaveFileName( lastPath, "Shaders (*.vp *.txt)");
00355 if(QString::null == s)
00356 return;
00357 _vpshader->setProgFile(s.ascii());
00358 }
00359 else
00360 {
00361 s = _vpshader->getProgFile();
00362 }
00363
00364 of.open(s.ascii(), ios::binary);
00365 if(of.bad())
00366 {
00367 _errw->launchError( "failed to open " + s + " for writing \n" );
00368 of.close();
00369 return;
00370 }
00371
00372 of.write(_vpshader->getProgText(), strlen(_vpshader->getProgText()));
00373
00374 if(of.bad())
00375 {
00376 _errw->launchError( "error writing " + s + "\n" );
00377 of.close();
00378 return;
00379 }
00380
00381 of.close();
00382 _mle->setModified(false);
00383 return;
00384 break;
00385 }
00386 }
00387
00388
00389
00390
00391 void PShaderTxt::saveShaderAs(const QString &lastPath)
00392 {
00393 QString s;
00394 ofstream of;
00395
00396 s = QFileDialog::getSaveFileName( lastPath, "Shaders (*.fp *.vp *.txt)");
00397 if(QString::null == s)
00398 return;
00399
00400 of.open(s.ascii(), ios::binary);
00401 if(of.bad())
00402 {
00403 _errw->launchError( "failed to open " + s + " for writing \n" );
00404 of.close();
00405 return;
00406 }
00407
00408 if(_mle->isModified())
00409 loadShader();
00410
00411 switch(_stype)
00412 {
00413 case ARB_FP:
00414 if(_fpshader.isNull()) return;
00415 _fpshader->setProgFile(s.ascii());
00416 of.write(_fpshader->getProgText(), strlen(_fpshader->getProgText()));
00417 break;
00418 case ARB_VP:
00419 if(_vpshader.isNull()) return;
00420 _vpshader->setProgFile(s.ascii());
00421 of.write(_vpshader->getProgText(), strlen(_vpshader->getProgText()));
00422 break;
00423 }
00424
00425 if(of.bad())
00426 {
00427 _errw->launchError( "error writing " + s + "\n" );
00428 }
00429
00430 of.close();
00431
00432 _mle->setModified(false);
00433 }
00434
00435
00436
00437
00438 void PShaderTxt::closeShader(const QString &lastPath)
00439 {
00440 if(_mle->isModified())
00441 {
00442 loadShader();
00443
00444 if(!QMessageBox::information(this,"Save File?",
00445 "This shader has not been saved, save now?",
00446 "Save","Cancel"))
00447 {
00448 saveShader(lastPath);
00449 }
00450 }
00451 }
00452
00453
00454
00455
00456 bool PShaderTxt::castShader()
00457 {
00458 if(_shader.isNull())
00459 {
00460 cerr << "PShaderTxt::castShader(), Shader is null!!!" << endl;
00461 return true;
00462 }
00463
00464
00465 if(_fpshader = dynamic_cast<FragProgARB*>(_shader.getPtr()))
00466 {
00467 _stype = ARB_FP;
00468 }
00469
00470 else if(_vpshader = dynamic_cast<VertexProgARB*>(_shader.getPtr()))
00471 {
00472 _stype = ARB_VP;
00473 }
00474
00475 else
00476 {
00477 cerr << "PShaderTxt::castShader(), shader type unknown " << endl;
00478 return true;
00479 }
00480
00481 return false;
00482 }
00483
00484
00485
00486
00487 const string ARB_ERR_CHAR("at character");
00488
00489 int PShaderTxt::getErrorPos(std::string s)
00490 {
00491 if(s.empty()) return -1;
00492
00493
00494 if(s.find(ARB_ERR_CHAR) != -1)
00495 {
00496 string epos = s.substr(s.find(ARB_ERR_CHAR) + ARB_ERR_CHAR.size(), 8);
00497 istringstream iss(epos);
00498 int p;
00499 iss >> p;
00500
00501 return s.find("!!ARB") + p;
00502 }
00503
00504 return -1;
00505 }
00506