From a606290ed2ec9540f8c24c52983f857511403bec Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Mon, 14 May 2012 06:40:18 +0000
Subject: [PATCH] gpu: allow to load a .lolfx file instead of all those
 shaders.

---
 src/Makefile.am                 |  2 +-
 src/gpu/shader.cpp              | 59 +++++++++++++++++++++++++++++++++
 src/gpu/shader.h                |  1 +
 test/tutorial/01_triangle.cpp   | 26 ++-------------
 test/tutorial/01_triangle.lolfx | 35 +++++++++++++++++++
 test/tutorial/Makefile.am       |  9 +++++
 win32/01_triangle.vcxproj       |  3 ++
 7 files changed, 111 insertions(+), 24 deletions(-)
 create mode 100644 test/tutorial/01_triangle.lolfx

diff --git a/src/Makefile.am b/src/Makefile.am
index cda3ff5f..48248302 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,7 +54,7 @@ SUFFIXES = .lolfx
 %.lolfx.cpp: %.lolfx
 	echo "/* This file was autogenerated. DO NOT MODIFY IT. */" > $@.tmp
 	echo "char const *lolfx_$(notdir $(^:%.lolfx=%)) =" >> $@.tmp
-	$(SED) 's/"/\\"/g' $^ | $(SED) 's/.*/"&"/' >> $@.tmp
+	$(SED) 's/"/\\"/g' $^ | $(SED) 's/.*/"&\\n"/' >> $@.tmp
 	echo ";" >> $@.tmp
 	mv $@.tmp $@
 
diff --git a/src/gpu/shader.cpp b/src/gpu/shader.cpp
index 42ea3d88..0350445c 100644
--- a/src/gpu/shader.cpp
+++ b/src/gpu/shader.cpp
@@ -82,6 +82,65 @@ int ShaderData::nshaders = 0;
  * Public Shader class
  */
 
+Shader *Shader::Create(char const *lolfx)
+{
+    char *src = new char[strlen(lolfx) + 2];
+    memcpy(src + 1, lolfx, strlen(lolfx) + 1);
+    src[0] = '\n';
+
+    /* Parse the crap */
+    Array<char const *, char const *> sections;
+    char *key = NULL;
+    for (char *parser = src; *parser; )
+    {
+        if (key == NULL && (parser[0] == '\n' || parser[0] == '\r')
+             && parser[1] == '-' && parser[2] == '-' && parser[3] == ' ')
+        {
+            *parser = '\0';
+            parser += 4;
+            key = parser;
+        }
+        else if (key && parser[0] == ' ')
+        {
+            *parser++ = '\0';
+        }
+        else if (key && (parser[0] == '\n' || parser[0] == '\r'))
+        {
+            sections.Push(key, parser);
+            parser++;
+            key = NULL;
+        }
+        else
+        {
+            parser++;
+        }
+    }
+
+    char const *vert = NULL, *frag = NULL;
+    for (int i = 0; i < sections.Count(); i++)
+    {
+#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
+        if (!strcmp(sections[i].m1, "GLSL.Vert"))
+            vert = sections[i].m2;
+        if (!strcmp(sections[i].m1, "GLSL.Frag"))
+            frag = sections[i].m2;
+#else
+        if (!strcmp(sections[i].m1, "HLSL.Vert"))
+            vert = sections[i].m2;
+        if (!strcmp(sections[i].m1, "HLSL.Frag"))
+            frag = sections[i].m2;
+#endif
+    }
+
+    Shader *ret = NULL;
+    if (vert && frag)
+        ret = Create(vert, frag);
+
+    delete[] src;
+
+    return ret;
+}
+
 Shader *Shader::Create(char const *vert, char const *frag)
 {
     uint32_t new_vert_crc = Hash::Crc32(vert);
diff --git a/src/gpu/shader.h b/src/gpu/shader.h
index 3828e323..5441bed3 100644
--- a/src/gpu/shader.h
+++ b/src/gpu/shader.h
@@ -51,6 +51,7 @@ class ShaderData;
 class Shader
 {
 public:
+    static Shader *Create(char const *lolfx);
     static Shader *Create(char const *vert, char const *frag);
     static void Destroy(Shader *shader);
 
diff --git a/test/tutorial/01_triangle.cpp b/test/tutorial/01_triangle.cpp
index f2b7efba..be11ca95 100644
--- a/test/tutorial/01_triangle.cpp
+++ b/test/tutorial/01_triangle.cpp
@@ -31,6 +31,8 @@ using namespace lol;
 #   include <direct.h>
 #endif
 
+extern char const *lolfx_01_triangle;
+
 class Triangle : public WorldEntity
 {
 public:
@@ -48,29 +50,7 @@ public:
 
         if (!m_ready)
         {
-            m_shader = Shader::Create(
-#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
-                "#version 120\n"
-                "attribute vec2 in_Position;"
-                "void main(void) {"
-                "    gl_Position = vec4(in_Position, 0.0, 1.0);"
-                "}",
-
-                "#version 120\n"
-                "void main(void) {"
-                "    gl_FragColor = vec4(0.7, 0.2, 0.5, 1.0);"
-                "}"
-#else
-                "void main(float2 in_Position : POSITION,"
-                "          out float4 out_Position : POSITION) {"
-                "    out_Position = float4(in_Position, 0.0, 1.0);"
-                "}",
-
-                "void main(out float4 out_FragColor : COLOR) {"
-                "    out_FragColor = float4(0.7, 0.2, 0.5, 1.0);"
-                "}"
-#endif
-            );
+            m_shader = Shader::Create(lolfx_01_triangle);
             m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0);
 
             m_vdecl = new VertexDeclaration(VertexStream<vec2>(VertexUsage::Position));
diff --git a/test/tutorial/01_triangle.lolfx b/test/tutorial/01_triangle.lolfx
new file mode 100644
index 00000000..6ec78e29
--- /dev/null
+++ b/test/tutorial/01_triangle.lolfx
@@ -0,0 +1,35 @@
+-- GLSL.Vert --
+
+#version 120
+
+attribute vec2 in_Position;
+
+void main(void)
+{
+    gl_Position = vec4(in_Position, 0.0, 1.0);
+}
+
+-- GLSL.Frag --
+
+#version 120
+
+void main(void)
+{
+    gl_FragColor = vec4(0.7, 0.2, 0.5, 1.0);
+}
+
+-- HLSL.Vert --
+
+void main(float2 in_Position : POSITION,
+          out float4 out_Position : POSITION)
+{
+    out_Position = float4(in_Position, 0.0, 1.0);
+}
+
+-- HLSL.Frag --
+
+void main(out float4 out_FragColor : COLOR)
+{
+    out_FragColor = float4(0.7, 0.2, 0.5, 1.0);
+}
+
diff --git a/test/tutorial/Makefile.am b/test/tutorial/Makefile.am
index 3aba5e59..2aaa2cb7 100644
--- a/test/tutorial/Makefile.am
+++ b/test/tutorial/Makefile.am
@@ -10,9 +10,18 @@ CLEANFILES = $(noinst_PROGRAMS:%$(EXEEXT)=%.self) \
              $(noinst_PROGRAMS:%$(EXEEXT)=%.elf) \
              $(noinst_PROGRAMS:%$(EXEEXT)=%.exe)
 
+SUFFIXES = .lolfx
+%.lolfx.cpp: %.lolfx
+	echo "/* This file was autogenerated. DO NOT MODIFY IT. */" > $@.tmp
+	echo "char const *lolfx_$(notdir $(^:%.lolfx=%)) =" >> $@.tmp
+	$(SED) 's/"/\\"/g' $^ | $(SED) 's/.*/"&\\n"/' >> $@.tmp
+	echo ";" >> $@.tmp
+	mv $@.tmp $@
+
 noinst_PROGRAMS = 01_triangle 02_cube 03_fractal
 
 01_triangle_SOURCES = 01_triangle.cpp
+nodist_01_triangle_SOURCES = 01_triangle.lolfx.cpp
 01_triangle_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
 01_triangle_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
 01_triangle_DEPENDENCIES = $(top_builddir)/src/liblol.a
diff --git a/win32/01_triangle.vcxproj b/win32/01_triangle.vcxproj
index 2ae22c13..af3f7dc4 100644
--- a/win32/01_triangle.vcxproj
+++ b/win32/01_triangle.vcxproj
@@ -29,6 +29,9 @@
   <ItemGroup>
     <ClCompile Include="..\test\tutorial\01_triangle.cpp" />
   </ItemGroup>
+  <ItemGroup>
+    <LolFxCompile Include="..\test\tutorial\01_triangle.lolfx" />
+  </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="lolcore.vcxproj">
       <Project>{9e62f2fe-3408-4eae-8238-fd84238ceeda}</Project>