+#include <psychlops.h>
+using namespace Psychlops; // Initially developed with Psychlops Win32 1.4.6 / 20100325
+
+std::string error_message;
+
+void loadGLSL(std::stringstream &buf, const std::string path)
+{
+ char one;
+ std::ifstream is;
+ is.open(path.c_str(), std::ifstream::in);
+ if(is.fail()) {
+ Widgets::Dialog::alert(L"File was not found, or failed to read for some reasons.");
+ return;
+ }
+ while(is.good()) {
+ is.get(one);
+ buf << one;
+ }
+}
+void logError()
+{
+ std::ofstream os;
+ os.open("GLSLTesterErrorLog.txt");
+ if(os.fail()) {
+ Widgets::Dialog::alert(L"File was not found, or failed to read for some reasons.");
+ return;
+ }
+ os << error_message;
+}
+
+const char *default_field_glsl =
+ "in float red;"
+ "void main(void){ "
+ "pix(red,0.0,0.0,1.0); }";
+
+Figures::ShaderField field;
+char *source_field = (char*)default_field_glsl;
+void cacheShaderField(const std::string path)
+{
+ std::stringstream buf;
+ loadGLSL(buf, path);
+
+ try{
+ field.setFunction(buf.str());
+ field.cache(*Display::the_canvas);
+ error_message.clear();
+ } catch (Exception e) {
+ error_message = e.getErrorString();
+ logError();
+ } catch (Exception *e) {
+ error_message = e->getErrorString();
+ logError();
+ }
+}
+
+const char *default_image_glsl =
+ "in float dr, dg, db, da;"
+ "void main(void) {"
+ "vec4 d = vec4(dr, dg, db, da);"
+ "pix(getPix()+d);}";
+Figures::ShaderImage image;
+char *source_image = (char*)default_image_glsl;
+Image shadered_image, dummy_image;
+void cacheShaderImage(const std::string path)
+{
+ std::stringstream buf;
+ loadGLSL(buf, path);
+ try{
+ image.setFunction(buf.str().c_str());
+ image.cache(*Display::the_canvas);
+ error_message.clear();
+ } catch (Exception e) {
+ error_message = e.getErrorString();
+ logError();
+ } catch (Exception *e) {
+ error_message = e->getErrorString();
+ logError();
+ }
+}
+
+
+
+
+class RangedSlider : public Widgets::WidgetRect
+{
+ public:
+ static Interval itvl[6];
+ static void initialize() {
+ 0<=itvl[0]<=1;
+ -1<=itvl[1]<=1;
+ 0<=itvl[2]<=100;
+ -100<=itvl[3]<=100;
+ 0<=itvl[4]<=2*PI;
+ -2*PI<=itvl[5]<=2*PI;
+ }
+ bool active;
+ Widgets::Slider slide;
+ Widgets::SelectBox box;
+ RangedSlider& set(std::string lab, double hei) {
+ const Color ic(0,0,1,0.7), oc(.5,.5,.5,.5);
+ slide.set(lab, itvl[0]);
+ slide.area.fill = oc;
+ slide.internal.fill = ic;
+ box.append(L"[0, 1]");
+ box.append(L"[-1, 1]");
+ box.append(L"[0, 100]");
+ box.append(L"[-100, 100]");
+ box.append(L"[0, 2PI]");
+ box.append(L"[-2PI, 2PI]");
+ area.set(slide.getWidth()/3, hei);
+ return *this;
+ }
+ RangedSlider& draw(Drawable &target = *Drawable::prime)
+ {
+ if(active) {
+ if(box.pushed()) {
+ double ratio = slide.getRatio();
+ slide.setInterval(itvl[box.getSelected()]);
+ slide.setByRatio(ratio);
+ }
+ slide.area.set(getWidth()-90, getHeight()).alignLeft(getLeft()).alignTop(getTop());
+ slide.draw(target);
+ box.area.set(88, getHeight()).alignRight(getRight()).alignTop(getTop());
+ box.draw(target);
+ }
+ return *this;
+ }
+};
+Interval RangedSlider::itvl[6];
+const int SHADER_ARG_MAX = 16;
+
+
+void ShaderTestTool() {
+
+ Canvas cnvs(800, 600, Canvas::window);
+
+ int view = 0;
+ const double DEFAULT_IMAGE_SIZE = 200.0;
+ shadered_image.set(DEFAULT_IMAGE_SIZE, DEFAULT_IMAGE_SIZE);
+ for(int x=0; x<DEFAULT_IMAGE_SIZE; x++) for(int y=0; y<DEFAULT_IMAGE_SIZE; y++) shadered_image.pix(x,y,Color(x/DEFAULT_IMAGE_SIZE, y/DEFAULT_IMAGE_SIZE, 0));
+ shadered_image.cache();
+
+
+ Widgets::StackPanel buttons;
+ Widgets::Button loader[3];
+ loader[0].set(L"Load GLSL/field", 18);
+ buttons.append(&loader[0]);
+ loader[1].set(L"Load GLSL/image", 18);
+ buttons.append(&loader[1]);
+ loader[2].set(L"Load PNG image", 18);
+ buttons.append(&loader[2]);
+ buttons.setWidth(150);
+ buttons.alignLeft(cnvs.getWidth() - 152).alignTop(cnvs.getHeight() - 18*4);
+ Drawable::billboard.append(buttons);
+
+
+ Psychlops::Rectangle area(300,300);
+ area.centering();
+
+ double Z[SHADER_ARG_MAX];
+ for(int i=0; i<SHADER_ARG_MAX; i++) Z[i] = 0.0;
+
+ RangedSlider sliders[SHADER_ARG_MAX];
+ RangedSlider::initialize();
+ Widgets::StackPanel panel;
+ std::stringstream wss;
+ for(int i=0; i<SHADER_ARG_MAX; i++) {
+ wss.str("");
+ wss << "var[" << i << "] ";
+ sliders[i].set("0", 18);
+ sliders[i].slide.label.setString(wss.str().c_str());
+ sliders[i].slide.link(Z[i], RangedSlider::itvl[0], 1);
+ panel.append(&sliders[i]);
+ }
+ panel.setWidth(200).shift(10,10);
+
+
+ std::string path[3];
+ Letters pathname[3];
+
+ std::string tmps;
+ field.setFunction(default_field_glsl);
+ field.cache(*Display::the_canvas);
+ for(int i=0; i<field.orig_args.size(); i++) {
+ tmps.assign(field.orig_args[i]).append(" ");
+ sliders[i].slide.label.setString(tmps.c_str());
+ sliders[i].active = true;
+ }
+ for(int i=field.orig_args.size(); i<SHADER_ARG_MAX; i++) {
+ sliders[i].active = false;
+ }
+// image.setFunction(default_image_glsl);
+// image.cache(*Display::the_canvas);
+
+ int error;
+
+ while(!Input::get(Keyboard::esc)) {
+ Display::clear();
+
+ if(loader[0].pushed()) {
+ try {
+ path[0] = Widgets::Dialog::getOpenFileName();
+ cacheShaderField(path[0]);
+ path[0].append(" OK ");
+ pathname[0].fill = Color::yellow;
+ error = 1;
+ view = 0;
+ for(int i=0; i<field.orig_args.size(); i++) {
+ tmps.assign(field.orig_args[i]).append(" ");
+ sliders[i].slide.label.setString(tmps.c_str());
+ sliders[i].active = true;
+ }
+ for(int i=field.orig_args.size(); i<SHADER_ARG_MAX; i++) {
+ sliders[i].active = false;
+ }
+ } catch(Exception e) {
+ path[0] = e.to_s();
+ pathname[0].fill = Color::red;
+ error = -1;
+ }
+ pathname[0].setString(path[0].c_str());
+ }
+ if(loader[1].pushed()) {
+ try {
+ path[1] = Widgets::Dialog::getOpenFileName();
+ cacheShaderImage(path[1]);
+ path[1].append(" OK ");
+ pathname[1].fill = Color::yellow;
+ error = 1;
+ view = 1;
+ for(int i=0; i<image.orig_args.size(); i++) {
+ tmps.assign(image.orig_args[i]).append(" ");
+ sliders[i].slide.label.setString(tmps.c_str());
+ sliders[i].active = true;
+ }
+ for(int i=image.orig_args.size(); i<SHADER_ARG_MAX; i++) {
+ sliders[i].active = false;
+ }
+ } catch(Exception e) {
+ path[1] = e.to_s();
+ pathname[1].fill = Color::red;
+ error = -1;
+ }
+ pathname[1].setString(path[1].c_str());
+ }
+ if(loader[2].pushed()) {
+ try {
+ path[2] = Widgets::Dialog::getOpenFileName();
+ dummy_image.load(path[2]);
+ shadered_image.load(path[2]);
+ shadered_image.cache();
+ path[2].append(" OK ");
+ pathname[2].fill = Color::yellow;
+ error = 1;
+ } catch(Exception e) {
+ path[2] = e.to_s();
+ pathname[2].fill = Color::red;
+ error = -1;
+ }
+ pathname[2].setString(path[2].c_str());
+ }
+
+ switch(view) {
+ case 1:
+ shadered_image.centering();
+ image.draw(shadered_image, Z, 3, *Display::the_canvas);
+ break;
+ case 0:
+ default:
+ field.draw(area, Z, 3, *Display::the_canvas);
+ break;
+ }
+ panel.draw();
+ buttons.draw();
+ for(int i=0; i<3; i++) {
+ pathname[i].font.size = 15;
+ pathname[i].locate(loader[i].area.getLeft() - 20, loader[i].area.getBottom()-2).align = Letters::TEXT_ALIGN_RIGHT;
+ pathname[i].draw();
+ }
+ if(!error_message.empty()) cnvs.msg(error_message, 200,20,Color::yellow);
+ cnvs.flip();
+ if(AppState::shouldBeClose) return;
+ }
+
+}
+
+
+void psychlops_main() {
+ Procedure p;
+ p.setDesign(Procedure::DEMO);
+ p.setProcedure(ShaderTestTool);
+ p.run();
+
+}
+