diff --git a/README.md b/README.md index 5bcd908..1dcd62d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ There are several different ways to create a project: The best thing about making a game in Clojure is that you can modify it in a REPL while it's running. By simply reloading a namespace, your code will be injected into the game, uninhibited by the restrictions posed by tools like HotSwap. Additionally, a REPL lets you read and modify the _state_ of your game at runtime, so you can quickly experiment and diagnose problems. -Clojure also brings the benefits of functional programming. This is becoming a big topic of discussion in gamedev circles, including by [John Carmack](http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/). Part of this is due to the prevalence of multi-core hardware, making concurrency more important. Additionally, there is a general difficulty of maintaining object-oriented game codebases as they grow, due to complicated class hierarchies and state mutations. +Clojure also brings the benefits of functional programming. This is becoming a big topic of discussion in gamedev circles, including by [John Carmack](http://gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php). Part of this is due to the prevalence of multi-core hardware, making concurrency more important. Additionally, there is a general difficulty of maintaining object-oriented game codebases as they grow, due to complicated class hierarchies and state mutations. ## Documentation diff --git a/TUTORIAL.md b/TUTORIAL.md index d9bbdbe..ffd9ea3 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -44,10 +44,10 @@ Right now, you're using the `play-clj.ui` library to display a label. This libra [play-clj.g2d :refer :all])) ``` -Now let's find an image to use as a texture in the game. Find one you'd like to use, such as [this Clojure logo](http://upload.wikimedia.org/wikipedia/commons/c/c5/Clojure-icon.gif), and save it to the `desktop/resources` folder. Next, simply change the line where the label entity is being created, so it creates a texture from that file instead: +Now let's find an image to use as a texture in the game. Find one you'd like to use, such as [this Clojure logo](http://upload.wikimedia.org/wikipedia/en/1/1d/Clojure_logo.gif), and save it to the `desktop/resources` folder. Next, simply change the line where the label entity is being created, so it creates a texture from that file instead: ```clojure - (texture "Clojure-icon.gif") + (texture "Clojure_logo.gif") ``` ## Size and Position @@ -61,14 +61,14 @@ If you run the code now, you'll see the image in the bottom-left corner. As ment A `texture` contains the underlying Java object. By default, it will be drawn at the bottom-left corner with the size of the image itself. You can change the position and size by simply using `assoc`: ```clojure - (assoc (texture "Clojure-icon.gif") + (assoc (texture "Clojure_logo.gif") :x 50 :y 50 :width 100 :height 100) ``` You can also set scaling and rotation on a texture using :scale-x, :scale-y, and :angle, which all use (:origin-x, :origin-y) as the center. For example, here we rotate it 45 degrees counter-clockwise around the bottom-left corner: ```clojure - (assoc (texture "Clojure-icon.gif") + (assoc (texture "Clojure_logo.gif") :x 50 :y 50 :width 100 :height 100 :angle 45 :origin-x 0 :origin-y 0) ``` @@ -117,13 +117,13 @@ The [game](http://oakes.github.io/play-clj/core.game.html) function gives you co :on-touch-down (fn [screen entities] (cond - (> (game :point-y) (* (game :height) (/ 2 3))) + (> (game :y) (* (game :height) (/ 2 3))) (println "up") - (< (game :point-y) (/ (game :height) 3)) + (< (game :y) (/ (game :height) 3)) (println "down") - (> (game :point-x) (* (game :width) (/ 2 3))) + (> (game :x) (* (game :width) (/ 2 3))) (println "right") - (< (game :point-x) (/ (game :width) 3)) + (< (game :x) (/ (game :width) 3)) (println "left"))) ``` @@ -162,13 +162,13 @@ Now we can update our `:on-key-down` and `:on-touch-down` functions to move the :on-touch-down (fn [screen entities] (cond - (> (game :point-y) (* (game :height) (/ 2 3))) + (> (game :y) (* (game :height) (/ 2 3))) (move (first entities) :up) - (< (game :point-y) (/ (game :height) 3)) + (< (game :y) (/ (game :height) 3)) (move (first entities) :down) - (> (game :point-x) (* (game :width) (/ 2 3))) + (> (game :x) (* (game :width) (/ 2 3))) (move (first entities) :right) - (< (game :point-x) (/ (game :width) 3)) + (< (game :x) (/ (game :width) 3)) (move (first entities) :left))) ``` @@ -252,13 +252,13 @@ At some point, you will need to do more than simple positioning and sizing. For In play-clj, many different calls, such as `texture`, are actually macros that allow you to call the underlying Java methods after the required argument(s). In this case, the underlying class is called [TextureRegion](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/TextureRegion.html). Consider this: ```clojure - (texture "Clojure-icon.gif" :flip true false) + (texture "Clojure_logo.gif" :flip true false) ``` ...which is transformed into: ```clojure - (let [entity (texture "Clojure-icon.gif")] + (let [entity (texture "Clojure_logo.gif")] (doto ^TextureRegion (:object entity) (.flip true false)) entity) @@ -267,7 +267,7 @@ In play-clj, many different calls, such as `texture`, are actually macros that a You can even call multiple methods in the same expression this way. For example: ```clojure - (texture "Clojure-icon.gif" + (texture "Clojure_logo.gif" :flip true false :set-region 0 0 100 100) ``` @@ -275,10 +275,10 @@ You can even call multiple methods in the same expression this way. For example: ...which is transformed into: ```clojure - (let [entity (texture "Clojure-icon.gif")] + (let [entity (texture "Clojure_logo.gif")] (doto ^TextureRegion (:object entity) (.flip true false) - (.setRegion 0 0 100 100) + (.setRegion 0 0 100 100)) entity) ``` diff --git a/doclet/resources/classes.edn b/doclet/resources/classes.edn index 8b93305..382493a 100644 --- a/doclet/resources/classes.edn +++ b/doclet/resources/classes.edn @@ -1,9 +1,9 @@ {"Actor" {"actor!" :methods} "ActorGestureListener" {"actor-gesture-listener!" :methods} - "Align" {"align" :static-fields} + "Align" {"align" :static-fields-camel} "com.badlogic.gdx.graphics.g2d.Animation" {"animation" :methods "animation!" :methods} - "Animation.PlayMode" {"play-mode" :static-fields} + "Animation.PlayMode" {"play-mode" :static-fields-upper} "AnimationController" {"animation-controller" :methods "animation-controller!" :methods} "Application" {"app!" :methods} @@ -19,7 +19,7 @@ "BitmapFont" {"bitmap-font" :methods "bitmap-font!" :methods} "BlendingAttribute" {"attribute :blending" :constructors - "attribute-type :blending" :static-fields + "attribute-type :blending" :static-fields-pascal "attribute! :blending" :static-methods} "Body" {"body!" :methods} "BodyDef" {"body-def" :fields} @@ -37,10 +37,10 @@ "CircleMapObject" {"map-object :circle" :methods} "ChangeListener" {"change-listener!" :methods} "ClickListener" {"click-listener!" :methods} - "Color" {"color" :static-fields + "Color" {"color" :static-fields-upper "color!" :methods} "ColorAttribute" {"attribute :color" :constructors - "attribute-type :color" :static-fields + "attribute-type :color" :static-fields-pascal "attribute! :color" :static-methods} "ConvexHull" {"convex-hull" :methods "convex-hull!" :methods} @@ -52,12 +52,12 @@ "CircleShape" {"circle-shape" :methods "circle-shape!" :methods} "CubemapAttribute" {"attribute :cubemap" :constructors - "attribute-type :cubemap" :static-fields + "attribute-type :cubemap" :static-fields-pascal "attribute! :cubemap" :static-methods} "DelaunayTriangulator" {"delaunay-triangulator" :methods "delaunay-triangulator!" :methods} "DepthTestAttribute" {"attribute :depth-test" :constructors - "attribute-type :depth-test" :static-fields + "attribute-type :depth-test" :static-fields-pascal "attribute! :depth-test" :static-methods} "Dialog" {"dialog" :methods "dialog!" :methods} @@ -76,7 +76,7 @@ "Fixture" {"fixture!" :methods} "FixtureDef" {"fixture-def" :fields} "FloatAttribute" {"attribute :float" :constructors - "attribute-type :float" :static-fields + "attribute-type :float" :static-fields-pascal "attribute! :float" :static-methods} "FloatCounter" {"float-counter" :methods "float-counter!" :methods} @@ -93,7 +93,7 @@ "GridPoint3" {"grid-point-3" :methods "grid-point-3!" :methods} "GL20" {"gl!" :methods - "gl" :static-fields} + "gl" :static-fields-upper} "HexagonalTiledMapRenderer" {"hexagonal-tiled-map" :methods "hexagonal-tiled-map!" :methods} "HorizontalGroup" {"horizontal" :methods @@ -107,15 +107,15 @@ "image-text-button!" :methods} "ImageTextButton.ImageTextButtonStyle" {"style :image-text-button" :constructors} "Input" {"input!" :methods} - "Input.Keys" {"key-code" :static-fields - "key-pressed?" :static-fields} - "Input.Buttons" {"button-code" :static-fields - "button-pressed?" :static-fields} + "Input.Keys" {"key-code" :static-fields-upper + "key-pressed?" :static-fields-upper} + "Input.Buttons" {"button-code" :static-fields-upper + "button-pressed?" :static-fields-upper} "InputProcessor" {"input-processor!" :methods} "Interpolation" {"interpolation" :static-classes} "Intersector" {"intersector!" :static-methods} "IntAttribute" {"attribute :int" :constructors - "attribute-type :int" :static-fields + "attribute-type :int" :static-fields-pascal "attribute! :int" :static-methods} "IsometricStaggeredTiledMapRenderer" {"isometric-staggered-tiled-map" :methods "isometric-staggered-tiled-map!" :methods} @@ -146,6 +146,8 @@ "ModelInstance" {"model" :constructors "model!" :methods} "MouseJointDef" {"joint-def :mouse" :fields} + "Music" {"music" :methods + "music!" :methods} "Net" {"net!" :methods} "NinePatch" {"nine-patch" :methods "nine-patch!" :methods} @@ -160,10 +162,10 @@ "perspective!" :methods} "Pixmap" {"pixmap" :methods "pixmap!" :methods} - "Pixmap.Format" {"pixmap-format" :static-fields} + "Pixmap.Format" {"pixmap-format" :static-fields-pascal} "Plane" {"plane" :methods "plane!" :methods} - "Plane.PlaneSide" {"plane-side" :static-fields} + "Plane.PlaneSide" {"plane-side" :static-fields-pascal} "Polygon" {"polygon" :methods "polygon!" :methods} "PolygonMapObject" {"map-object :polygon" :methods} @@ -185,7 +187,7 @@ "RectangleMapObject" {"map-object :rectangle" :methods} "RevoluteJointDef" {"joint-def :revolute" :fields} "RopeJointDef" {"joint-def :rope" :fields} - "Scaling" {"scaling" :static-fields} + "Scaling" {"scaling" :static-fields-camel} "ScrollPane" {"scroll-pane" :methods "scroll-pane!" :methods} "ScrollPane.ScrollPaneStyle" {"style :scroll-pane" :constructors} @@ -196,7 +198,7 @@ "SelectBox.SelectBoxStyle" {"style :select-box" :constructors} "ShapeRenderer" {"shape" :methods "shape!" :methods} - "ShapeRenderer.ShapeType" {"shape-type" :static-fields} + "ShapeRenderer.ShapeType" {"shape-type" :static-fields-pascal} "Skin" {"skin" :methods "skin!" :methods} "Slider" {"slider" :methods @@ -216,7 +218,7 @@ "TextureAtlas" {"texture-atlas" :methods "texture-atlas!" :methods} "TextureAttribute" {"attribute :texture" :constructors - "attribute-type :texture" :static-fields + "attribute-type :texture" :static-fields-pascal "attribute! :texture" :static-methods} "TextButton" {"text-button" :methods "text-button!" :methods} @@ -242,7 +244,7 @@ "vector-2!" :methods} "Vector3" {"vector-3" :methods "vector-3!" :methods} - "VertexAttributes.Usage" {"usage" :static-fields} + "VertexAttributes.Usage" {"usage" :static-fields-pascal} "VerticalGroup" {"vertical" :methods "vertical!" :methods} "WeldJointDef" {"joint-def :weld" :fields} diff --git a/doclet/resources/highlight.css b/doclet/resources/highlight.css index e479d0a..835d746 100644 --- a/doclet/resources/highlight.css +++ b/doclet/resources/highlight.css @@ -1,12 +1,14 @@ -/* - -Dark style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ +/** + * Obsidian style + * ported by Alexander Marenin (http://github.com/ioncreature) + */ .hljs { - display: block; padding: 0.5em; - background: #444; + display: block; + overflow-x: auto; + padding: 0.5em; + background: #282b2e; + -webkit-text-size-adjust: none; } .hljs-keyword, @@ -14,36 +16,77 @@ Dark style from softwaremaniacs.org (c) Ivan Sagalaev /gm,">")}function t(v){return v.nodeName.toLowerCase()}function i(w,x){var v=w&&w.exec(x);return v&&v.index==0}function d(v){return Array.prototype.map.call(v.childNodes,function(w){if(w.nodeType==3){return b.useBR?w.nodeValue.replace(/\n/g,""):w.nodeValue}if(t(w)=="br"){return"\n"}return d(w)}).join("")}function r(w){var v=(w.className+" "+(w.parentNode?w.parentNode.className:"")).split(/\s+/);v=v.map(function(x){return x.replace(/^language-/,"")});return v.filter(function(x){return j(x)||x=="no-highlight"})[0]}function o(x,y){var v={};for(var w in x){v[w]=x[w]}if(y){for(var w in y){v[w]=y[w]}}return v}function u(x){var v=[];(function w(y,z){for(var A=y.firstChild;A;A=A.nextSibling){if(A.nodeType==3){z+=A.nodeValue.length}else{if(t(A)=="br"){z+=1}else{if(A.nodeType==1){v.push({event:"start",offset:z,node:A});z=w(A,z);v.push({event:"stop",offset:z,node:A})}}}}return z})(x,0);return v}function q(w,y,C){var x=0;var F="";var z=[];function B(){if(!w.length||!y.length){return w.length?w:y}if(w[0].offset!=y[0].offset){return(w[0].offset"}function E(G){F+=""}function v(G){(G.event=="start"?A:E)(G.node)}while(w.length||y.length){var D=B();F+=k(C.substr(x,D[0].offset-x));x=D[0].offset;if(D==w){z.reverse().forEach(E);do{v(D.splice(0,1)[0]);D=B()}while(D==w&&D.length&&D[0].offset==x);z.reverse().forEach(A)}else{if(D[0].event=="start"){z.push(D[0].node)}else{z.pop()}v(D.splice(0,1)[0])}}return F+k(C.substr(x))}function m(y){function v(z){return(z&&z.source)||z}function w(A,z){return RegExp(v(A),"m"+(y.cI?"i":"")+(z?"g":""))}function x(D,C){if(D.compiled){return}D.compiled=true;D.k=D.k||D.bK;if(D.k){var z={};function E(G,F){if(y.cI){F=F.toLowerCase()}F.split(" ").forEach(function(H){var I=H.split("|");z[I[0]]=[G,I[1]?Number(I[1]):1]})}if(typeof D.k=="string"){E("keyword",D.k)}else{Object.keys(D.k).forEach(function(F){E(F,D.k[F])})}D.k=z}D.lR=w(D.l||/\b[A-Za-z0-9_]+\b/,true);if(C){if(D.bK){D.b=D.bK.split(" ").join("|")}if(!D.b){D.b=/\B|\b/}D.bR=w(D.b);if(!D.e&&!D.eW){D.e=/\B|\b/}if(D.e){D.eR=w(D.e)}D.tE=v(D.e)||"";if(D.eW&&C.tE){D.tE+=(D.e?"|":"")+C.tE}}if(D.i){D.iR=w(D.i)}if(D.r===undefined){D.r=1}if(!D.c){D.c=[]}var B=[];D.c.forEach(function(F){if(F.v){F.v.forEach(function(G){B.push(o(F,G))})}else{B.push(F=="self"?D:F)}});D.c=B;D.c.forEach(function(F){x(F,D)});if(D.starts){x(D.starts,C)}var A=D.c.map(function(F){return F.bK?"\\.?\\b("+F.b+")\\b\\.?":F.b}).concat([D.tE]).concat([D.i]).map(v).filter(Boolean);D.t=A.length?w(A.join("|"),true):{exec:function(F){return null}};D.continuation={}}x(y)}function c(S,L,J,R){function v(U,V){for(var T=0;T";U+=Z+'">';return U+X+Y}function N(){var U=k(C);if(!I.k){return U}var T="";var X=0;I.lR.lastIndex=0;var V=I.lR.exec(U);while(V){T+=U.substr(X,V.index-X);var W=E(I,V);if(W){H+=W[1];T+=w(W[0],V[0])}else{T+=V[0]}X=I.lR.lastIndex;V=I.lR.exec(U)}return T+U.substr(X)}function F(){if(I.sL&&!f[I.sL]){return k(C)}var T=I.sL?c(I.sL,C,true,I.continuation.top):g(C);if(I.r>0){H+=T.r}if(I.subLanguageMode=="continuous"){I.continuation.top=T.top}return w(T.language,T.value,false,true)}function Q(){return I.sL!==undefined?F():N()}function P(V,U){var T=V.cN?w(V.cN,"",true):"";if(V.rB){D+=T;C=""}else{if(V.eB){D+=k(U)+T;C=""}else{D+=T;C=U}}I=Object.create(V,{parent:{value:I}})}function G(T,X){C+=T;if(X===undefined){D+=Q();return 0}var V=v(X,I);if(V){D+=Q();P(V,X);return V.rB?0:X.length}var W=z(I,X);if(W){var U=I;if(!(U.rE||U.eE)){C+=X}D+=Q();do{if(I.cN){D+=""}H+=I.r;I=I.parent}while(I!=W.parent);if(U.eE){D+=k(X)}C="";if(W.starts){P(W.starts,"")}return U.rE?0:X.length}if(A(X,I)){throw new Error('Illegal lexeme "'+X+'" for mode "'+(I.cN||"")+'"')}C+=X;return X.length||1}var M=j(S);if(!M){throw new Error('Unknown language: "'+S+'"')}m(M);var I=R||M;var D="";for(var K=I;K!=M;K=K.parent){if(K.cN){D=w(K.cN,D,true)}}var C="";var H=0;try{var B,y,x=0;while(true){I.t.lastIndex=x;B=I.t.exec(L);if(!B){break}y=G(L.substr(x,B.index-x),B[0]);x=B.index+y}G(L.substr(x));for(var K=I;K.parent;K=K.parent){if(K.cN){D+=""}}return{r:H,value:D,language:S,top:I}}catch(O){if(O.message.indexOf("Illegal")!=-1){return{r:0,value:k(L)}}else{throw O}}}function g(y,x){x=x||b.languages||Object.keys(f);var v={r:0,value:k(y)};var w=v;x.forEach(function(z){if(!j(z)){return}var A=c(z,y,false);A.language=z;if(A.r>w.r){w=A}if(A.r>v.r){w=v;v=A}});if(w.language){v.second_best=w}return v}function h(v){if(b.tabReplace){v=v.replace(/^((<[^>]+>|\t)+)/gm,function(w,z,y,x){return z.replace(/\t/g,b.tabReplace)})}if(b.useBR){v=v.replace(/\n/g,"
")}return v}function p(z){var y=d(z);var A=r(z);if(A=="no-highlight"){return}var v=A?c(A,y,true):g(y);var w=u(z);if(w.length){var x=document.createElementNS("http://www.w3.org/1999/xhtml","pre");x.innerHTML=v.value;v.value=q(w,u(x),y)}v.value=h(v.value);z.innerHTML=v.value;z.className+=" hljs "+(!A&&v.language||"");z.result={language:v.language,re:v.r};if(v.second_best){z.second_best={language:v.second_best.language,re:v.second_best.r}}}var b={classPrefix:"hljs-",tabReplace:null,useBR:false,languages:undefined};function s(v){b=o(b,v)}function l(){if(l.called){return}l.called=true;var v=document.querySelectorAll("pre code");Array.prototype.forEach.call(v,p)}function a(){addEventListener("DOMContentLoaded",l,false);addEventListener("load",l,false)}var f={};var n={};function e(v,x){var w=f[v]=x(this);if(w.aliases){w.aliases.forEach(function(y){n[y]=v})}}function j(v){return f[v]||f[n[v]]}this.highlight=c;this.highlightAuto=g;this.fixMarkup=h;this.highlightBlock=p;this.configure=s;this.initHighlighting=l;this.initHighlightingOnLoad=a;this.registerLanguage=e;this.getLanguage=j;this.inherit=o;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE]};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE]};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.TM={cN:"title",b:this.IR,r:0};this.UTM={cN:"title",b:this.UIR,r:0}}();hljs.registerLanguage("clojure",function(l){var e={built_in:"def cond apply if-not if-let if not not= = < < > <= <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"};var f="[a-zA-Z_0-9\\!\\.\\?\\-\\+\\*\\/\\<\\=\\>\\&\\#\\$';]+";var a="[\\s:\\(\\{]+\\d+(\\.\\d+)?";var d={cN:"number",b:a,r:0};var j=l.inherit(l.QSM,{i:null});var o={cN:"comment",b:";",e:"$",r:0};var n={cN:"collection",b:"[\\[\\{]",e:"[\\]\\}]"};var c={cN:"comment",b:"\\^"+f};var b={cN:"comment",b:"\\^\\{",e:"\\}"};var h={cN:"attribute",b:"[:]"+f};var m={cN:"list",b:"\\(",e:"\\)"};var g={eW:true,k:{literal:"true false nil"},r:0};var i={k:e,l:f,cN:"title",b:f,starts:g};m.c=[{cN:"comment",b:"comment"},i,g];g.c=[m,j,c,b,o,h,n,d];n.c=[m,j,c,o,h,n,d];return{i:/\S/,c:[o,m,{cN:"prompt",b:/^=> /,starts:{e:/\n\n|\Z/}}]}}); \ No newline at end of file +!function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){var n=(e.className+" "+(e.parentNode?e.parentNode.className:"")).split(/\s+/);return n=n.map(function(e){return e.replace(/^lang(uage)?-/,"")}),n.filter(function(e){return N(e)||/no(-?)highlight/.test(e)})[0]}function o(e,n){var t={};for(var r in e)t[r]=e[r];if(n)for(var r in n)t[r]=n[r];return t}function i(e){var n=[];return function r(e,a){for(var o=e.firstChild;o;o=o.nextSibling)3==o.nodeType?a+=o.nodeValue.length:1==o.nodeType&&(n.push({event:"start",offset:a,node:o}),a=r(o,a),t(o).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:o}));return a}(e,0),n}function c(e,r,a){function o(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function c(e){l+=""}function u(e){("start"==e.event?i:c)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=o();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){f.reverse().forEach(c);do u(g.splice(0,1)[0]),g=o();while(g==e&&g.length&&g[0].offset==s);f.reverse().forEach(i)}else"start"==g[0].event?f.push(g[0].node):f.pop(),u(g.splice(0,1)[0])}return l+n(a.substr(s))}function u(e){function n(e){return e&&e.source||e}function t(t,r){return RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var c={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");c[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):Object.keys(a.k).forEach(function(e){u(e,a.k[e])}),a.k=c}a.lR=t(a.l||/\b[A-Za-z0-9_]+\b/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function s(e,t,a,o){function i(e,n){for(var t=0;t";return o+=e+'">',o+n+i}function d(){if(!w.k)return n(y);var e="",t=0;w.lR.lastIndex=0;for(var r=w.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(w,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=w.lR.lastIndex,r=w.lR.exec(y)}return e+n(y.substr(t))}function h(){if(w.sL&&!R[w.sL])return n(y);var e=w.sL?s(w.sL,y,!0,L[w.sL]):l(y);return w.r>0&&(B+=e.r),"continuous"==w.subLanguageMode&&(L[w.sL]=e.top),p(e.language,e.value,!1,!0)}function v(){return void 0!==w.sL?h():d()}function b(e,t){var r=e.cN?p(e.cN,"",!0):"";e.rB?(M+=r,y=""):e.eB?(M+=n(t)+r,y=""):(M+=r,y=t),w=Object.create(e,{parent:{value:w}})}function m(e,t){if(y+=e,void 0===t)return M+=v(),0;var r=i(t,w);if(r)return M+=v(),b(r,t),r.rB?0:t.length;var a=c(w,t);if(a){var o=w;o.rE||o.eE||(y+=t),M+=v();do w.cN&&(M+=""),B+=w.r,w=w.parent;while(w!=a.parent);return o.eE&&(M+=n(t)),y="",a.starts&&b(a.starts,""),o.rE?0:t.length}if(f(t,w))throw new Error('Illegal lexeme "'+t+'" for mode "'+(w.cN||"")+'"');return y+=t,t.length||1}var x=N(e);if(!x)throw new Error('Unknown language: "'+e+'"');u(x);for(var w=o||x,L={},M="",k=w;k!=x;k=k.parent)k.cN&&(M=p(k.cN,"",!0)+M);var y="",B=0;try{for(var C,j,I=0;;){if(w.t.lastIndex=I,C=w.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}m(t.substr(I));for(var k=w;k.parent;k=k.parent)k.cN&&(M+="");return{r:B,value:M,language:e,top:w}}catch(A){if(-1!=A.message.indexOf("Illegal"))return{r:0,value:n(t)};throw A}}function l(e,t){t=t||E.languages||Object.keys(R);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(N(n)){var t=s(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function f(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,E.tabReplace)})),E.useBR&&(e=e.replace(/\n/g,"
")),e}function g(e,n,t){var r=n?x[n]:t,a=[e.trim()];return e.match(/(\s|^)hljs(\s|$)/)||a.push("hljs"),r&&a.push(r),a.join(" ").trim()}function p(e){var n=a(e);if(!/no(-?)highlight/.test(n)){var t;E.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e;var r=t.textContent,o=n?s(n,r,!0):l(r),u=i(t);if(u.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=o.value,o.value=c(u,i(p),r)}o.value=f(o.value),e.innerHTML=o.value,e.className=g(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){E=o(E,e)}function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",h,!1),addEventListener("load",h,!1)}function b(n,t){var r=R[n]=t(e);r.aliases&&r.aliases.forEach(function(e){x[e]=n})}function m(){return Object.keys(R)}function N(e){return R[e]||R[x[e]]}var E={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},R={},x={};return e.highlight=s,e.highlightAuto=l,e.fixMarkup=f,e.highlightBlock=p,e.configure=d,e.initHighlighting=h,e.initHighlightingOnLoad=v,e.registerLanguage=b,e.listLanguages=m,e.getLanguage=N,e.inherit=o,e.IR="[a-zA-Z][a-zA-Z0-9_]*",e.UIR="[a-zA-Z_][a-zA-Z0-9_]*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.CLCM={cN:"comment",b:"//",e:"$",c:[e.PWM]},e.CBCM={cN:"comment",b:"/\\*",e:"\\*/",c:[e.PWM]},e.HCM={cN:"comment",b:"#",e:"$",c:[e.PWM]},e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("clojure",function(e){var t={built_in:"def cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},r="a-zA-Z_\\-!.?+*=<>&#'",n="["+r+"]["+r+"0-9/;:]*",a="[-+]?\\d+(\\.\\d+)?",o={b:n,r:0},s={cN:"number",b:a,r:0},c=e.inherit(e.QSM,{i:null}),i={cN:"comment",b:";",e:"$",r:0},d={cN:"literal",b:/\b(true|false|nil)\b/},l={cN:"collection",b:"[\\[\\{]",e:"[\\]\\}]"},m={cN:"comment",b:"\\^"+n},p={cN:"comment",b:"\\^\\{",e:"\\}"},u={cN:"attribute",b:"[:]"+n},f={cN:"list",b:"\\(",e:"\\)"},h={eW:!0,r:0},y={k:t,l:n,cN:"keyword",b:n,starts:h},b=[f,c,m,p,i,u,l,s,d,o];return f.c=[{cN:"comment",b:"comment"},y,h],h.c=b,l.c=b,{aliases:["clj"],i:/\S/,c:[f,c,m,p,i,u,l,s,d]}}); \ No newline at end of file diff --git a/doclet/resources/main.css b/doclet/resources/main.css index 82e2ddd..d0fb416 100644 --- a/doclet/resources/main.css +++ b/doclet/resources/main.css @@ -1,39 +1,64 @@ body { - font-family: "Trebuchet MS", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif; + font-family: "Fira Sans", "Source Sans Pro", "Helvetica Neue", sans-serif; background-color: #293134; color: #c1cbc2; + font-size: 16px; + line-height: 1.4em; } + a { - color: #c1cbc2; + transition-property: color; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(.53,.4,.46,.75); + color: #f2ecd7; + box-shadow: 0 2px 0 0 rgba(255,255,255,0.1); + text-decoration: none; +} + +a:hover { + color: #f2dc77; } .sidebar { - width: 240px; - height: 100%; - top: 0px; - left: 0px; - position: fixed; - overflow: auto; - margin-left: 10px; + transition-property: opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(.53,.4,.46,.75); + opacity: 0.6; } -.sidebar a { - text-decoration: none; +.sidebar:hover { + opacity: 0.9; } .ns { font-size: 24px; - font-weight: bold; + padding: 20px 0 0px 0; + margin-bottom: 10px; + display: inline-block; + color: #ccf; } .name { margin-top: 5px; margin-bottom: 5px; + text-indent: 10px; } .content { - margin-left: 250px; + padding: 20px 0px 20px 20px; +} + +.content code { + box-shadow: 0 0 0 1px rgba(255,255,255,0.2); + border-radius: 3px; + padding: 0px 3px; + background: rgba(255,255,255,0.1); + text-shadow: 0 1px 0 rgba(0,0,0,0.5); +} + +.content code, .content pre { + font-family: "Fira Mono", "Source Code Poro", "Consolas", "Menlo", monospace; } .item { @@ -41,41 +66,65 @@ a { } .clj { - + margin-bottom: 2em; } .c-head { font-size: 20px; - font-weight: bold; - margin-bottom: 10px; + margin-bottom: 1em; + color: #ccf; + font-size: 1.5em; } .c-doc { - } .c-src { - + margin-bottom: 2em; } .java { - background: #444444; + margin-bottom: 2em; } .j-text { margin-bottom: 5px; } -.j-item { - margin-bottom: 10px; +.j-item * { + transition-property: opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(.53,.4,.46,.75); } +.j-item { + margin-bottom: 0px; + padding: 0.8em 0 0.8em 0; + line-height: 1.4em; + background: rgba(0, 0, 0, 0.15); +} +.j-item:nth-child(2n) { + background: rgba(0, 0, 0, 0.25); +} .j-name { - font-weight: bold; + color: #69e; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.8); + margin: 0 0px 0 20px; + display: inline-block; + font-size: 1.4em; + line-height: 1.4em; + border-right: 5px transparent solid; + box-shadow: 0 2px 0 0 rgba(150,200,255,0.08); } .j-args { - margin-left: 5px; + padding-left: 1em; + opacity: 0.4; + display: inline-block; +} + +.j-item:hover .j-args { + opacity: 0.95; } .j-arg { @@ -87,4 +136,7 @@ a { } .j-doc { + display: block; + padding: 17px 20px 0px 20px; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.5); } diff --git a/doclet/resources/main.js b/doclet/resources/main.js index a254ba7..6a15493 100644 --- a/doclet/resources/main.js +++ b/doclet/resources/main.js @@ -1,4 +1,4 @@ var elems = document.getElementsByTagName("pre"); for (var i = 0; i < elems.length; i++) { hljs.highlightBlock(elems[i]); -} \ No newline at end of file +} diff --git a/doclet/resources/nav.js b/doclet/resources/nav.js new file mode 100644 index 0000000..530f1d2 --- /dev/null +++ b/doclet/resources/nav.js @@ -0,0 +1,9 @@ +function goToHash() { + if (window.location.hash != "") { + document.getElementById("content-frame").src = window.location.hash.substr(1) + } +} + +function setHash(link) { + window.parent.location.hash = link.getAttribute("newHash") +} diff --git a/doclet/src/clojure/play_clj_doclet/core.clj b/doclet/src/clojure/play_clj_doclet/core.clj index 060a13e..cdf77f3 100644 --- a/doclet/src/clojure/play_clj_doclet/core.clj +++ b/doclet/src/clojure/play_clj_doclet/core.clj @@ -13,49 +13,55 @@ (def classes (-> "classes.edn" io/resource slurp edn/read-string)) -(defn split-string - [s] - (if (= s (string/upper-case s)) - (string/split s #"_") - (string/split s #"(?=[A-Z])"))) - (defn string->keyword - [s] - (->> (split-string s) + [s case-type] + (->> (case case-type + :upper #"_" + :pascal #"(?<=.)(?=[A-Z])" + :camel #"(?=[A-Z])" + (throw (Exception. "Unrecognized case type."))) + (string/split s) (map string/lower-case) (string/join "-") keyword)) (defn parse-param [^Parameter p] - [(.typeName p) (-> (.name p) string->keyword name)]) + [(.typeName p) (-> (.name p) (string->keyword :camel) name)]) + +(defn after-last-period + [^String s] + (subs s (+ 1 (.lastIndexOf s ".")))) (defn parse-doc-name - [^Doc d] - (cond - (isa? (type d) ConstructorDoc) + [^String doc-name doc-type] + (case doc-type + :constructors nil - - (isa? (type d) ClassDoc) - (->> (+ 1 (.lastIndexOf (.name d) ".")) - (subs (.name d)) - string->keyword) - - (isa? (type d) FieldDoc) - (let [k (string->keyword (.name d)) - s (name k)] - (if (= \- (first s)) - (keyword (subs s 1)) - k)) - - :else - (string->keyword (.name d)))) + + :classes + (string->keyword (after-last-period doc-name) :pascal) + + :static-classes + (string->keyword (after-last-period doc-name) :pascal) + + :static-fields-upper + (string->keyword doc-name :upper) + + :static-fields-pascal + (string->keyword doc-name :pascal) + + :static-fields-camel + (string->keyword doc-name :camel) + + ; else + (string->keyword doc-name :camel))) (defn parse-doc - [^Doc d clj-name] + [^Doc d clj-name doc-type] (merge {} {:name (->> [(second (string/split clj-name #" ")) - (parse-doc-name d)] + (parse-doc-name (.name d) doc-type)] (remove nil?) (string/join " "))} (when (> (count (.commentText d)) 0) @@ -70,18 +76,20 @@ {:args [[(-> d .type .typeName) "value"]]}))) (defn parse-class-entry - [^ClassDoc c [clj-name type]] - (some->> (case type + [^ClassDoc c [clj-name doc-type]] + (some->> (case doc-type :methods (filter #(-> % .isStatic not) (.methods c)) :static-methods (filter #(.isStatic %) (.methods c)) :fields (filter #(-> % .isStatic not) (.fields c)) - :static-fields (filter #(.isStatic %) (.fields c)) + :static-fields-upper (filter #(.isStatic %) (.fields c)) + :static-fields-pascal (filter #(.isStatic %) (.fields c)) + :static-fields-camel (filter #(.isStatic %) (.fields c)) :classes (filter #(-> % .isStatic not) (.innerClasses c)) :static-classes (filter #(.isStatic %) (.innerClasses c)) :constructors (filter #(-> % .isStatic not) (.constructors c)) nil) (filter #(.isPublic %)) - (map #(parse-doc % clj-name)) + (map #(parse-doc % clj-name doc-type)) (concat (when-let [sc (.superclass c)] (when (not= (.typeName sc) "Object") (parse-class-entry sc [clj-name type])))) diff --git a/doclet/src/clojure/play_clj_doclet/html.clj b/doclet/src/clojure/play_clj_doclet/html.clj index 11fa3bf..adb5cd0 100644 --- a/doclet/src/clojure/play_clj_doclet/html.clj +++ b/doclet/src/clojure/play_clj_doclet/html.clj @@ -20,7 +20,7 @@ (cons [:div {:class "ns"} ns] (for [{:keys [name]} groups] [:div {:class "name"} - [:a {:href (str->filename ns name)} + [:a {:href (str->filename ns name) :target "content-frame" :onClick (str "setHash(this)") :newHash (str->filename ns name)} name]])))]) (defn java-param @@ -41,12 +41,17 @@ [:div {:class "j-doc"} text])]) (defn content - [{:keys [name docstring arglists java raw raw*]}] + [{:keys [name docstring arglists java raw raw*]} & [home-link-hash]] [:div {:class "content"} [:div {:class "item"} [:div {:class "clj"} (for [args arglists] - [:div {:class "c-head"} (pr-str args)]) + [:div {:class "c-head"} + (if home-link-hash + [:a {:href (str "index.html" (str "#" home-link-hash)) + :target "_top"} + (pr-str args)] + (pr-str args))]) [:div {:class "c-doc"} docstring]] (when (> (count java) 0) (list [:div {:class "c-head"} "Options"] @@ -61,17 +66,17 @@ [:pre raw]]]]) (defn create-site-file - [name sidebar content] - (html [:html - [:head - [:title name] - [:link {:rel "stylesheet" :href "highlight.css"}] - [:link {:rel "stylesheet" :href "main.css"}]] - [:body - sidebar - content - [:script {:src "highlight.js"}] - [:script {:src "main.js"}]]])) + ([name content] + (html [:html + [:head + [:title name] + [:script {:src "nav.js"}] + [:link {:rel "stylesheet" :href "highlight.css"}] + [:link {:rel "stylesheet" :href "main.css"}]] + [:body + content + [:script {:src "highlight.js"}] + [:script {:src "main.js"}]]]))) (defn create-embed-file [content] @@ -82,19 +87,39 @@ (spit (io/file dir file-name) (-> file-name io/resource slurp))) +(defn index-frameset + [] + (html + [:html + [:head + [:title "play-clj docs"] + [:script {:src "nav.js"}] + [:link {:rel "stylesheet" :href "highlight.css"}] + [:link {:rel "stylesheet" :href "main.css"}]] + [:frameset {:cols "250px,100%" :onLoad "goToHash();"} + [:frame {:src "sidebar.html"}] + [:frame {:src "blank.html" :name "content-frame" :id "content-frame"}] + [:script {:src "highlight.js"}] + [:script {:src "main.js"}]]])) + (defn create-site! [dir parsed-files] (.mkdir (io/file dir)) (copy-from-res dir "main.css") (copy-from-res dir "main.js") + (copy-from-res dir "nav.js") (copy-from-res dir "highlight.css") (copy-from-res dir "highlight.js") (doseq [[ns groups] parsed-files] (doseq [{:keys [name] :as group} groups] (spit (io/file dir (str->filename ns name)) - (create-site-file name (sidebar parsed-files) (content group))))) + (create-site-file name (content group (str->filename ns name)))))) + (spit (io/file dir "sidebar.html") + (create-site-file "sidebar" (sidebar parsed-files))) + (spit (io/file dir "blank.html") + (create-site-file "blank" nil)) (spit (io/file dir "index.html") - (create-site-file "play-clj docs" (sidebar parsed-files) nil)) + (index-frameset)) (println "Created" (str dir "/"))) (defn create-embed! diff --git a/project.clj b/project.clj index bcb15fc..c911d46 100644 --- a/project.clj +++ b/project.clj @@ -1,11 +1,11 @@ -(defproject play-clj "0.4.2-SNAPSHOT" +(defproject play-clj "0.4.5-SNAPSHOT" :description "A libGDX wrapper for easy cross-platform game development" :url "https://github.com/oakes/play-clj" :license {:name "Public Domain" :url "http://unlicense.org/UNLICENSE"} - :dependencies [[com.badlogicgames.gdx/gdx "1.4.1"] - [com.badlogicgames.gdx/gdx-box2d "1.4.1"] - [com.badlogicgames.gdx/gdx-bullet "1.4.1"] + :dependencies [[com.badlogicgames.gdx/gdx "1.5.3"] + [com.badlogicgames.gdx/gdx-box2d "1.5.3"] + [com.badlogicgames.gdx/gdx-bullet "1.5.3"] [org.clojure/clojure "1.6.0"]] :repositories [["sonatype" "https://oss.sonatype.org/content/repositories/releases/"]] diff --git a/src/play_clj/core.clj b/src/play_clj/core.clj index a079f36..34155b5 100644 --- a/src/play_clj/core.clj +++ b/src/play_clj/core.clj @@ -172,7 +172,8 @@ via the screen map. entities)) ; input functions - ; Tip: convert :input-x and :input-y to screen coordinates with input->screen + ; Tip: convert :input-x and :input-y to screen coordinates with input->screen, + ; or just use (game :x) and (game :y) instead (defscreen my-screen ; a key was pressed :on-key-down @@ -225,7 +226,6 @@ via the screen map. entities)) ; gesture functions - ; Tip: use gesture-detector! to configure these functions (defscreen my-screen ; the user dragged over the screen and lifted :on-fling @@ -322,21 +322,13 @@ via the screen map. entities)) ; ui input functions (for play-clj.ui) - ; Tip: use click-listener! to configure these functions (defscreen my-screen - ; the ui entity was changed + ; the ui entity was clicked or changed :on-ui-changed (fn [screen entities] (println (:event screen)) ; the ChangeListener.ChangeEvent - http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/utils/ChangeListener.ChangeEvent.html (println (:actor screen)) ; the Actor - http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/Actor.html entities) - ; the ui entity was clicked - :on-ui-clicked - (fn [screen entities] - (println (:event screen)) ; the InputEvent - http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/InputEvent.html - (println (:input-x screen)) ; the x position of the finger/mouse - (println (:input-y screen)) ; the y position of the finger/mouse - entities) ; the finger/mouse moved over the ui entity :on-ui-enter (fn [screen entities] @@ -383,7 +375,6 @@ via the screen map. entities)) ; ui drag functions (for play-clj.ui) - ; Tip: use drag-listener! to configure these functions (defscreen my-screen :on-ui-drag (fn [screen entities] @@ -517,6 +508,10 @@ keywords and functions in pairs." (set-screen! my-game main-screen text-screen)" [^Game game-object & screen-objects] + (doseq [screen screen-objects] + (assert (every? #(fn? (get screen %)) + [:show :render :hide :pause :resize :resume]) + "Attempted to set an invalid screen.")) (let [run-fn! (fn [k & args] (doseq [screen screen-objects] (apply (get screen k) args)))] diff --git a/src/play_clj/core_basics.clj b/src/play_clj/core_basics.clj index 86fc1ff..e9d2cfb 100644 --- a/src/play_clj/core_basics.clj +++ b/src/play_clj/core_basics.clj @@ -101,10 +101,10 @@ :fps (graphics! :get-frames-per-second) :fullscreen? (graphics! :is-fullscreen) :touched? (input! :is-touched) - :x (throw (Exception. "Replace (game :x) with (input! :get-x)")) - :y (throw (Exception. "Replace (game :y) with (input! :get-y)")) - :point-x (input! :get-x (or arg 0)) - :point-y (- (graphics! :get-height) (input! :get-y (or arg 0))) + :x (input! :get-x (or arg 0)) + :y (- (graphics! :get-height) (input! :get-y (or arg 0))) + :point-x (game :x arg) + :point-y (game :y arg) (u/throw-key-not-found k))) (defmacro key-code @@ -153,7 +153,7 @@ (audio! :new-sound (files! :internal path)))) (defmacro sound - "Returns a [Sound](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/audio/Sound.html). + "Returns a [Sound](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/audio/Sound.html). Supports wav, mp3, and ogg. (sound \"playerhurt.wav\") (sound \"playerhurt.wav\" :play)" @@ -170,29 +170,25 @@ `(let [^Sound object# ~object] (u/call! object# ~k ~@options))) - (defn music* - [path] - (let [^FileHandle fh (if (string? path) - (files! :internal path) - path)] - (or (u/load-asset (.path fh) Music) - (audio! :new-music fh)))) + [^String path] + (or (u/load-asset path Music) + (audio! :new-music (files! :internal path)))) (defmacro music - "Returns a [Sound](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/audio/Sound.html). + "Returns a [Music](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/audio/Music.html). Supports wav, mp3, and ogg. - (sound \"playerhurt.wav\") - (sound \"playerhurt.wav\" :play)" + (music \"song.wav\") + (music \"song.wav\" :play)" [path & options] `(let [^Music object# (music* ~path)] (u/calls! object# ~@options))) (defmacro music! - "Calls a single method on a `sound`. + "Calls a single method on a `music`. - (sound! object :play) - (sound! object :dispose)" + (music! object :play) + (music! object :dispose)" [object k & options] `(let [^Music object# ~object] (u/call! object# ~k ~@options))) diff --git a/src/play_clj/core_cameras.clj b/src/play_clj/core_cameras.clj index 8a6445b..389a389 100644 --- a/src/play_clj/core_cameras.clj +++ b/src/play_clj/core_cameras.clj @@ -165,14 +165,13 @@ of the camera will be set." "Sets the position of `object`. If `object` is a screen, the position of the camera will be set." ([object vec-3] - (let [^Camera camera (u/get-obj object :camera)] - (set! (. camera position) vec-3))) + (position! object (x vec-3) (y vec-3) (z vec-3))) ([object x-val y-val] (position! object x-val y-val nil)) ([object x-val y-val z-val] - (when x-val (x! object x-val)) - (when y-val (y! object y-val)) - (when z-val (z! object z-val)))) + (some->> x-val (x! object)) + (some->> y-val (y! object)) + (some->> z-val (z! object)))) (defn direction "Returns the direction of the camera in `screen`." @@ -182,9 +181,24 @@ camera will be set." (defn direction! "Sets the direction of the camera in `screen`." - [screen x y z] + [screen x-val y-val z-val] (let [^Camera camera (u/get-obj screen :camera)] - (.lookAt camera x y z) + (.lookAt camera x-val y-val z-val) + (.update camera))) + +(defn up [screen] + "Returns the up vector of the camera in `screen`." + (let [^Camera camera (u/get-obj screen :camera)] + (. camera up))) + +(defn up! + "Sets the up vector of the camera in `screen`." + [screen x-val y-val z-val] + (let [^Camera camera (u/get-obj screen :camera) + ^Vector3 up-vec (up screen)] + (some->> x-val (x! up-vec)) + (some->> y-val (y! up-vec)) + (some->> z-val (z! up-vec)) (.update camera))) (defn near diff --git a/src/play_clj/core_graphics.clj b/src/play_clj/core_graphics.clj index 66a2b59..c30feb9 100644 --- a/src/play_clj/core_graphics.clj +++ b/src/play_clj/core_graphics.clj @@ -478,7 +478,7 @@ with the tiled map file at `path` and `unit` scale. (defmethod draw! BatchTiledMapRenderer [{:keys [^BatchTiledMapRenderer renderer] :as screen} entities] - (let [^Batch batch (.getSpriteBatch renderer)] + (let [^Batch batch (.getBatch renderer)] (.begin batch) (doseq [entity entities] (e/draw! entity screen batch)) @@ -610,7 +610,7 @@ to overlap correctly with the entities. (when-not (get-in screen [:layers ln]) (update-fn! assoc-in [:layers ln] (split-layer screen ln)))) (when camera (.setView renderer camera)) - (let [^Batch batch (.getSpriteBatch renderer)] + (let [^Batch batch (.getBatch renderer)] (.begin batch) (doseq [entity (->> (map #(get-in screen [:layers %]) layer-names) (apply concat entities) diff --git a/src/play_clj/g2d_physics.clj b/src/play_clj/g2d_physics.clj index e27b69d..16a534d 100644 --- a/src/play_clj/g2d_physics.clj +++ b/src/play_clj/g2d_physics.clj @@ -184,8 +184,6 @@ such as :on-begin-contact." (defmacro circle-shape "Returns a [CircleShape](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/physics/box2d/CircleShape.html)." [& options] - (when (some-> (first options) keyword? not) - (throw (Exception. "Replace (circle-shape radius) with (circle-shape :set-radius radius :set-position (vector-2 radius radius))"))) `(u/calls! ^CircleShape (circle-shape*) ~@options)) (defmacro circle-shape! diff --git a/src/play_clj/utils.clj b/src/play_clj/utils.clj index a8d506a..968fb31 100644 --- a/src/play_clj/utils.clj +++ b/src/play_clj/utils.clj @@ -153,7 +153,7 @@ new object to be created each time a field is set). (defn gdx-array* [clj-arr] - (Array. true (into-array clj-arr) 1 (count clj-arr))) + (Array. (into-array clj-arr))) (defmacro gdx-array "Returns an [Array](http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Array.html). diff --git a/template/project.clj b/template/project.clj index 78591f2..2916b36 100644 --- a/template/project.clj +++ b/template/project.clj @@ -1,8 +1,8 @@ -(defproject play-clj/lein-template "0.4.1" +(defproject play-clj/lein-template "0.4.4" :description "A template for making play-clj projects" :url "https://github.com/oakes/play-clj" :license {:name "Public Domain" :url "http://unlicense.org/UNLICENSE"} - :dependencies [[lein-droid "0.2.3"]] + :dependencies [[lein-droid "0.3.3"]] :resource-paths ["resources"] :eval-in-leiningen true) diff --git a/template/resources/armeabi-v7a/libgdx-box2d.so b/template/resources/armeabi-v7a/libgdx-box2d.so index 14575fc..923eff0 100644 Binary files a/template/resources/armeabi-v7a/libgdx-box2d.so and b/template/resources/armeabi-v7a/libgdx-box2d.so differ diff --git a/template/resources/armeabi-v7a/libgdx-bullet.so b/template/resources/armeabi-v7a/libgdx-bullet.so index b4ad643..b567acb 100644 Binary files a/template/resources/armeabi-v7a/libgdx-bullet.so and b/template/resources/armeabi-v7a/libgdx-bullet.so differ diff --git a/template/resources/armeabi-v7a/libgdx.so b/template/resources/armeabi-v7a/libgdx.so index 6bb9980..b224b0c 100644 Binary files a/template/resources/armeabi-v7a/libgdx.so and b/template/resources/armeabi-v7a/libgdx.so differ diff --git a/template/resources/armeabi/libgdx-box2d.so b/template/resources/armeabi/libgdx-box2d.so index 2a0ba51..521ac2d 100644 Binary files a/template/resources/armeabi/libgdx-box2d.so and b/template/resources/armeabi/libgdx-box2d.so differ diff --git a/template/resources/armeabi/libgdx-bullet.so b/template/resources/armeabi/libgdx-bullet.so index 994e6b9..f29d666 100644 Binary files a/template/resources/armeabi/libgdx-bullet.so and b/template/resources/armeabi/libgdx-bullet.so differ diff --git a/template/resources/armeabi/libgdx.so b/template/resources/armeabi/libgdx.so index 9e4119b..c6cdb9a 100644 Binary files a/template/resources/armeabi/libgdx.so and b/template/resources/armeabi/libgdx.so differ diff --git a/template/resources/ios/libObjectAL.a b/template/resources/ios/libObjectAL.a index 95969cb..64a843e 100644 Binary files a/template/resources/ios/libObjectAL.a and b/template/resources/ios/libObjectAL.a differ diff --git a/template/resources/ios/libgdx-box2d.a b/template/resources/ios/libgdx-box2d.a index 0e53e41..d32d665 100644 Binary files a/template/resources/ios/libgdx-box2d.a and b/template/resources/ios/libgdx-box2d.a differ diff --git a/template/resources/ios/libgdx-bullet.a b/template/resources/ios/libgdx-bullet.a index e5d6c33..9ff9bcd 100644 Binary files a/template/resources/ios/libgdx-bullet.a and b/template/resources/ios/libgdx-bullet.a differ diff --git a/template/resources/ios/libgdx.a b/template/resources/ios/libgdx.a index 549d913..371d37b 100644 Binary files a/template/resources/ios/libgdx.a and b/template/resources/ios/libgdx.a differ diff --git a/template/resources/x86/libgdx-box2d.so b/template/resources/x86/libgdx-box2d.so index dd2b3ab..03d1913 100644 Binary files a/template/resources/x86/libgdx-box2d.so and b/template/resources/x86/libgdx-box2d.so differ diff --git a/template/resources/x86/libgdx-bullet.so b/template/resources/x86/libgdx-bullet.so index a55c068..9d27915 100644 Binary files a/template/resources/x86/libgdx-bullet.so and b/template/resources/x86/libgdx-bullet.so differ diff --git a/template/resources/x86/libgdx.so b/template/resources/x86/libgdx.so index 6afee9c..de5b800 100644 Binary files a/template/resources/x86/libgdx.so and b/template/resources/x86/libgdx.so differ diff --git a/template/src/leiningen/new/play_clj.clj b/template/src/leiningen/new/play_clj.clj index 9845fbe..952a02a 100644 --- a/template/src/leiningen/new/play_clj.clj +++ b/template/src/leiningen/new/play_clj.clj @@ -58,7 +58,7 @@ (render "AndroidLauncher.java" data)] "android/src/clojure" ["android/AndroidManifest.xml" - (lein-droid-render "AndroidManifest.xml" data)] + (render "AndroidManifest.xml" data)] ["android/res/drawable-hdpi/ic_launcher.png" (lein-droid-render "ic_launcher_hdpi.png")] ["android/res/drawable-mdpi/ic_launcher.png" diff --git a/template/src/leiningen/new/play_clj/AndroidManifest.xml b/template/src/leiningen/new/play_clj/AndroidManifest.xml new file mode 100644 index 0000000..8425587 --- /dev/null +++ b/template/src/leiningen/new/play_clj/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/template/src/leiningen/new/play_clj/android-project.clj b/template/src/leiningen/new/play_clj/android-project.clj index c034341..1e302a7 100644 --- a/template/src/leiningen/new/play_clj/android-project.clj +++ b/template/src/leiningen/new/play_clj/android-project.clj @@ -1,15 +1,14 @@ (defproject {{app-name}} "0.0.1-SNAPSHOT" :description "FIXME: write description" - :dependencies [[com.badlogicgames.gdx/gdx "1.4.1" :use-resources true] - [com.badlogicgames.gdx/gdx-backend-android "1.4.1"] - [com.badlogicgames.gdx/gdx-box2d "1.4.1"] - [com.badlogicgames.gdx/gdx-bullet "1.4.1"] - [neko/neko "3.0.2"] + :dependencies [[com.badlogicgames.gdx/gdx "1.5.3" :use-resources true] + [com.badlogicgames.gdx/gdx-backend-android "1.5.3"] + [com.badlogicgames.gdx/gdx-box2d "1.5.3"] + [com.badlogicgames.gdx/gdx-bullet "1.5.3"] + [neko/neko "3.1.1"] [org.clojure-android/clojure "1.6.0-RC1" :use-resources true] - [play-clj "0.4.1"]] - :profiles {:dev {:dependencies [[android/tools.nrepl "0.2.0-bigstack"] - [compliment "0.1.3"]] + [play-clj "0.4.4"]] + :profiles {:dev {:dependencies [[org.clojure-android/tools.nrepl "0.2.6"]] :android {:aot :all-with-unused}} :release {:android {;; Specify the path to your private @@ -26,7 +25,7 @@ ;; Uncomment this if dexer fails with OutOfMemoryException ;; :force-dex-optimize true - :assets-path "../desktop/resources" + :assets-paths ["../desktop/resources"] :native-libraries-paths ["libs"] :target-version "{{target-sdk}}" :aot-exclude-ns ["clojure.parallel" "clojure.core.reducers"] diff --git a/template/src/leiningen/new/play_clj/desktop-project.clj b/template/src/leiningen/new/play_clj/desktop-project.clj index f8905b0..8fb6e1c 100644 --- a/template/src/leiningen/new/play_clj/desktop-project.clj +++ b/template/src/leiningen/new/play_clj/desktop-project.clj @@ -1,18 +1,18 @@ (defproject {{app-name}} "0.0.1-SNAPSHOT" :description "FIXME: write description" - :dependencies [[com.badlogicgames.gdx/gdx "1.4.1"] - [com.badlogicgames.gdx/gdx-backend-lwjgl "1.4.1"] - [com.badlogicgames.gdx/gdx-box2d "1.4.1"] - [com.badlogicgames.gdx/gdx-box2d-platform "1.4.1" + :dependencies [[com.badlogicgames.gdx/gdx "1.5.3"] + [com.badlogicgames.gdx/gdx-backend-lwjgl "1.5.3"] + [com.badlogicgames.gdx/gdx-box2d "1.5.3"] + [com.badlogicgames.gdx/gdx-box2d-platform "1.5.3" :classifier "natives-desktop"] - [com.badlogicgames.gdx/gdx-bullet "1.4.1"] - [com.badlogicgames.gdx/gdx-bullet-platform "1.4.1" + [com.badlogicgames.gdx/gdx-bullet "1.5.3"] + [com.badlogicgames.gdx/gdx-bullet-platform "1.5.3" :classifier "natives-desktop"] - [com.badlogicgames.gdx/gdx-platform "1.4.1" + [com.badlogicgames.gdx/gdx-platform "1.5.3" :classifier "natives-desktop"] [org.clojure/clojure "1.6.0"] - [play-clj "0.4.1"]] + [play-clj "0.4.4"]] :source-paths ["src" "src-common"] :javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"] diff --git a/template/src/leiningen/new/play_clj/ios-project.clj b/template/src/leiningen/new/play_clj/ios-project.clj index fb161b9..3b16acb 100644 --- a/template/src/leiningen/new/play_clj/ios-project.clj +++ b/template/src/leiningen/new/play_clj/ios-project.clj @@ -1,11 +1,11 @@ (defproject {{app-name}} "0.0.1-SNAPSHOT" :description "FIXME: write description" - :dependencies [[com.badlogicgames.gdx/gdx "1.4.1"] - [com.badlogicgames.gdx/gdx-backend-robovm "1.4.1"] - [com.badlogicgames.gdx/gdx-box2d "1.4.1"] - [com.badlogicgames.gdx/gdx-bullet "1.4.1"] + :dependencies [[com.badlogicgames.gdx/gdx "1.5.3"] + [com.badlogicgames.gdx/gdx-backend-robovm "1.5.3"] + [com.badlogicgames.gdx/gdx-box2d "1.5.3"] + [com.badlogicgames.gdx/gdx-bullet "1.5.3"] [org.clojure/clojure "1.6.0"] - [play-clj "0.4.1"]] + [play-clj "0.4.4"]] :source-paths ["src/clojure" "../desktop/src-common"] :java-source-paths ["src/java"] :javac-options ["-target" "1.7" "-source" "1.7" "-Xlint:-options"]