Changeset 343

Show
Ignore:
Timestamp:
05/28/08 13:29:08 (6 months ago)
Author:
FeepingCreature
Message:
  • Stuff n_n
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/qd/SDL_ttf.d

    r340 r343  
    55 
    66struct fontsettings { 
    7   bool bold=false; 
    8   bool italic=false; 
    9   bool underline=false; 
     7  bool bold, italic, underline; 
     8  rgb color=Black; int size=14; 
    109} 
    1110 
    1211import std.string: toStringz, toString; 
    1312import std.file: read; 
     13import tools.base; 
    1414 
    1515const SDL_Color SDL_White={255, 255, 255, 0}; 
    1616 
    17 TTF_FontClass standard; 
     17TTF_FontClass[int] standard; 
    1818void initFont(int size = 14, string name="Vera.ttf") { 
    19   standard=new TTF_FontClass(read(name), size); 
    20 
    21  
    22 void print(int x, int y, Align how, string what) { 
    23   if (!standard) initFont(); 
    24   auto surf=standard.render(what); 
     19  standard[size] = new TTF_FontClass(read(name), size); 
     20
     21 
     22int htoi(string s) { 
     23  int res; 
     24  foreach (ch; s) { 
     25    if (ch >= '0' && ch <= '9') { res = res * 16 + (ch - '0'); continue; } 
     26    if (ch >= 'a' && ch <= 'f') ch -= ('a' - 'A'); 
     27    if (ch >= 'A' && ch <= 'F') { res = res * 16 + (ch - 'A') + 10; continue; } 
     28    throw new Exception("Not a hexadecimal string: "~s); 
     29  } 
     30  return res; 
     31
     32 
     33void prettyprint(int x, int y, Align how, string text, fontsettings deflt = Init!(fontsettings)) { 
     34  string[] chunks; 
     35  fontsettings[] sets; 
     36  Stuple!(string, fontsettings)[] stack; 
     37  fontsettings fs_top() { 
     38    if (stack.length) { 
     39      return stack[$-1]._1; 
     40    } else return deflt; 
     41  } 
     42  fontsettings fs_pop(string compare) { 
     43    if (stack[$-1]._0 != compare) 
     44      throw new Exception("Mismatched closing tag: expected "~stack[$-1]._0~", got "~compare); 
     45    return .pop(stack)._1; 
     46  } 
     47  void push(string text, string tag, void delegate(ref fontsettings fs) dg) { 
     48    chunks ~= text; 
     49    sets ~= fs_top(); 
     50    stack ~= stuple(tag, fs_top()); dg(stack[$-1]._1); 
     51  } 
     52  void pop(string text, string tag) { 
     53    chunks ~= text; 
     54    sets ~= fs_pop(tag); 
     55  } 
     56  void delegate(string, ref string) close_tag(string _tag) { 
     57    return _tag /apply/ (string tag, string pre, ref string post) { pop(pre, tag); }; 
     58  } 
     59  void delegate(string, ref string) [string] tags = [ 
     60    "[b]"[]: (string pre, ref string post) { 
     61      push(pre, "b", (ref fontsettings fs) { fs.bold = true; }); 
     62    }, "[/b]": close_tag("b"), 
     63    "[i]": (string pre, ref string post) { 
     64      push(pre, "i", (ref fontsettings fs) { fs.italic = true; }); 
     65    }, "[/i]": close_tag("i"), 
     66    "[u]": (string pre, ref string post) { 
     67      push(pre, "u", (ref fontsettings fs) { fs.underline = true; }); 
     68    }, "[/u]": close_tag("u"), 
     69    "[color ": (string pre, ref string post) { 
     70      string color; ptuple(color, post) = post.splitAt("]"); 
     71      //                            color.length != 3 || color.length != 6 -- see, it's shorter :) 
     72      if (!color.startsWith("#") || color.length != 3 /or/ 6) 
     73        throw new Exception("Colors except #xxx and #xxxxxx not supported."); 
     74      color = color [1 .. $]; 
     75      if (color.length == 3) color = color[0]~"0"~color[1]~"0"~color[2]~"0"; 
     76      auto res = rgb(color[0 .. 2].htoi(), color[2 .. 4].htoi(), color[4 .. 6].htoi()); 
     77      push(pre, "color", (ref fontsettings fs) { fs.color = res; logln("fs.color: ", fs.color); }); 
     78    }, "[/color]": close_tag("color") 
     79  ]; 
     80  text.glomp_parse(tags, (string s) { 
     81    if (stack.length) throw new Exception("Unclosed tag: "~stack[$-1]._0); 
     82    if (s.length) { chunks ~= s; sets ~= deflt; } 
     83  }); 
     84  print(x, y, how, sets, chunks); 
     85
     86 
     87void print(int x, int y, Align how, fontsettings[] settings, string[] strings) in { 
     88    assert(settings.length == strings.length); 
     89  } body { 
     90  auto surfs = new Area[strings.length]; 
     91  int width, height; 
     92  foreach (i, str; strings) { 
     93    auto s = settings[i]; 
     94    if (!(s.size in standard)) initFont(s.size); 
     95    surfs[i] = standard[s.size].render(str, s); 
     96    width += surfs[i].width; 
     97    if (surfs[i].height > height) height = surfs[i].height; 
     98  } 
     99  auto target = display.select(pt(x, y), pt(width, height), how); 
     100  foreach (surf; surfs) { 
     101    target.blit(surf, Top|Left); 
     102    target.width = surf.width - width; // yes this is correct. 
     103    width -= surf.width; 
     104  } 
     105
     106 
     107void print(int x, int y, Align how, rgb col, string what) { 
     108  if (!(14 in standard)) initFont(); 
     109  fontsettings foo; foo.color = col; 
     110  auto surf=standard[14].render(what, foo); 
    25111  display.select(surf.size, pt(x, y), how).blit(surf); 
    26112  SDL_FreeSurface(surf.surface); 
    27113} 
    28114 
    29 void print(pt p, Align how, string what) { print(p.x, p.y, how, what); } 
    30 void print(Area where, Align how, string what) { 
    31   if (!standard) initFont(); 
    32   auto surf = standard.render(what); 
    33   where.blit(surf, how); 
    34   SDL_FreeSurface(surf.surface); 
    35 
     115void print(pt p, Align how, rgb col, string what) { print(p.x, p.y, how, col, what); } 
    36116 
    37117import std.stdio; 
     
    50130  } 
    51131  int curStyle; 
    52   private SDL_Surface *_render(char[] text, SDL_Color fg, fontsettings s=Default, int rendermode=2, SDL_Color *bg=null) { 
     132  private SDL_Surface *_render(char[] text, fontsettings s=Default, int rendermode=2, SDL_Color *bg=null) { 
    53133    //logln("Rendering ", text); 
    54134    /// Make sure no two routines change font settings at the same time 
     
    61141      switch(rendermode) { 
    62142        case 0: // Solid 
    63           return TTF_RenderUTF8_Solid(font, toStringz(text), fg); 
     143          return TTF_RenderUTF8_Solid(font, toStringz(text), s.color.toSDL()); 
    64144        case 1: // Shaded 
    65145          if (!bg) throw new Exception("Shaded selected but no background color given"); 
    66           return TTF_RenderUTF8_Shaded(font, toStringz(text), fg, *bg); 
     146          return TTF_RenderUTF8_Shaded(font, toStringz(text), s.color.toSDL(), *bg); 
    67147        case 2: // Blended 
    68           return TTF_RenderUTF8_Blended(font, toStringz(text), fg); 
     148          return TTF_RenderUTF8_Blended(font, toStringz(text), s.color.toSDL()); 
    69149        default: throw new Exception("Invalid case"); 
    70150      } 
     
    72152    assert(false); 
    73153  } 
    74   Area render(string text, SDL_Color fg=SDL_White, fontsettings s=Default) { 
    75     auto res=_render(text, fg, s); 
     154  Area render(string text, fontsettings s=Default) { 
     155    if (!text.length) return Area(SDL_CreateRGBSurface(0, 0, 0, 32)); 
     156    auto res=_render(text, s); 
    76157    if (!res) throw new Exception("Couldn't render "~'"'~text~'"'~": "~.toString(SDL_GetError)); 
    77158    return Area(pt(0, 0), pt(res.w, res.h), res); 
  • trunk/qd/dsss.conf

    r342 r343  
    33type=sourcelibrary 
    44[dt.d] 
    5 buildflags=-L-lSDL -g -profile 
     5buildflags=-L-lSDL -L-lSDL_ttf -g -O 
    66# [test.d] 
    77# buildflags=-L-lSDL 
    88[test2.d] 
    9 buildflags=-L-lSDL -L-lSDL_ttf -g -O -release -inline 
     9buildflags=-L-lSDL -L-lSDL_ttf -g 
    1010[cellular.d] 
    1111buildflags=-L-lSDL -g -J. -O -release -inline -q,-march=nocona 
     
    2525[test11.d] 
    2626buildflags=-L-lSDL -L-lSDL_ttf -g 
    27 [test12.d] 
    28 buildflags=-L-lSDL -L-lSDL_ttf -g 
     27# [test12.d] 
     28# buildflags=-L-lSDL -L-lSDL_ttf -g 
    2929[ff.d] 
    3030buildflags=-L-lSDL -L-lSDL_ttf -O 
    31 [test13.d] 
    32 buildflags=-L-lSDL -O -release -inline 
     31# [test13.d] 
     32# buildflags=-L-lSDL -L-lSDL_ttf -O -release -inline 
  • trunk/qd/dt.d

    r339 r343  
    66import std.stdio, std.c.time: time; 
    77import std.math, std.random, std.perf; 
    8 import qd
     8import qd, dglut.vector
    99 
    1010float randf() { return (cast(float)rand())/(cast(float)(typeof(rand()).max)); } 
     
    1919 
    2020class WorldThing : Thing { 
    21   int x, y, radius; 
    22   mixin This!("x, y, radius"); 
     21  vec2f pos; 
     22  int radius; 
     23  mixin This!("pos, radius"); 
    2324  bool collide(WorldThing other) { return distance(other)<radius+other.radius; } 
    24   float distance(WorldThing other) { 
    25     static int sqr(int e) { return e*e; } 
    26     return sqrt(cast(float)(sqr(x-other.x)+sqr(y-other.y))); 
    27   } 
     25  float distance(WorldThing other) { return (other.pos - pos).length(); } 
    2826} 
    2927 
    3028class LivingThing : WorldThing { 
    3129  private { 
    32     float life; 
     30    int life; 
    3331    void delegate(LivingThing) onDeath; 
    3432  } 
    35   void damage(float howmuch) { life-=howmuch; if (life!>0) onDeath(this); } 
    36   mixin This!("onDeath, super(x, y, radius), life=10"); 
     33  void damage(int howmuch) { life-=howmuch; if (life!>0) onDeath(this); } 
     34  void die() { damage(life); onDeath(this); } 
     35  mixin This!("onDeath, super(pos, radius), life=10"); 
    3736} 
    3837 
    3938interface MovingThing { 
    40   void getMotionVector(ref float dx, ref float dy); 
    41 
    42  
     39  vec2f getMotionVector(); 
     40
     41 
     42import dglut.vector; 
    4343class Path { 
    44   struct Point { 
    45     float x, y; 
    46     static Point opCall(float x, float y) { Point res; res.x=x; res.y=y; return res; } 
    47   } 
    48   Point[] points; 
     44  vec2f[] points; 
    4945  bool loop; 
    50   this(bool loop, Point[] points...) { this.loop=loop; this.points=points; } 
     46  this(bool loop, vec2f[] points...) { this.loop=loop; this.points=points.dup; } 
    5147  class Train { 
    5248    private { 
    5349      size_t cur; 
    5450      float speed; 
    55       Point pos; 
     51      vec2f pos; 
    5652      void delegate() done; 
    5753    } 
    58     float dx, dy
     54    vec2f delta
    5955    mixin This!("pos, speed, done, cur=0"); 
    6056    void update() { 
     
    6359      // find the next point that's more than 1 unit away from me 
    6460      do { 
    65         dx=points[cur].x-pos.x; dy=points[cur].y-pos.y
    66         len=sqrt(dx*dx+dy*dy); 
     61        delta = points[cur] - pos
     62        len = delta.length(); 
    6763      } while (len!>1 && (++cur)<points.length); 
    6864      if (cur==points.length) { 
     
    7066        return; 
    7167      } 
    72       dx/=len/speed; dy/=len/speed; 
    73       pos.x+=dx; pos.y+=dy
     68      delta /= len/speed; 
     69      pos += delta
    7470    } 
    7571  } 
     
    113109  //void draw() { circle(x, y, radius, Black, Fill=Blue~White~White); } 
    114110  void draw() { 
    115     bufferedCircle(x, y, radius, Black, Fill=Blue~White~White); 
    116     if (life<maxlife) circle(x, y, cast(int)(radius*0.8*(1f-life/maxlife)), Fill=Background); 
    117   } 
    118   void getMotionVector(ref float dx, ref float dy) { dx=train.dx; dy=train.dy; } 
     111    bufferedCircle(pos.to!(int).tuple, radius, Black, Fill=Blue~White~White); 
     112    if (life<maxlife) circle(pos.to!(int).tuple, cast(int)(radius*0.8*(1f-life * 1f / maxlife)), Background~Red, Fill=Background~Red); 
     113    .print(pos.to!(int).tuple, Center, Black, Format(life)); 
     114  } 
     115  override vec2f getMotionVector() { return train.delta; } 
    119116  void damage(typeof(life) d) { 
    120117    super.damage(d); 
    121     if (life!>0) addEffect!(RingEffect)(Blue~White~White, x, y, 10, 15); 
     118    if (life!>0) addEffect!(RingEffect)(Blue~White~White, pos, 10, 15); 
    122119  } 
    123120  void update() { 
    124121    train.update; 
    125     x=cast(int)train.pos.x; 
    126     y=cast(int)train.pos.y; 
     122    pos = train.pos; 
    127123  } 
    128124  float speed; 
    129   void die() { onDeath(this); life=0; } 
    130125  void delegate() win; 
    131126  private { 
    132     float maxlife; 
     127    int maxlife; 
    133128    Path path; 
    134129    Path.Train train; 
    135130    void initTrain() { 
    136       train=path.new Train(Path.Point(x, y), speed, win); 
     131      train=path.new Train(pos, speed, win); 
    137132    } 
    138133    long id; 
    139134  } 
    140   mixin This!("path, speed, win, id, super(onDeath, x, y, radius=20, life=20), #maxlife=life; #initTrain; "); 
    141 
    142  
    143 float distance(float x, float y, float x2, float y2) { 
    144   return sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2)); 
    145 
    146  
    147 void normalize(ref float x, ref float y, float div) { 
    148   auto len=x*x+y*y; 
    149   if (len==0) return; 
    150   len=sqrt(len); 
    151   x/=len/div; y/=len/div; 
     135  mixin This!("path, speed, win, id, super(onDeath, pos, radius=20, life=20), #maxlife=life; #initTrain; "); 
    152136} 
    153137 
    154138class Rocket : LivingThing { 
    155139  TargetGroup targets; 
    156   float fx, fy; 
    157   float dx=0f, dy=0f; 
     140  vec2f delta; 
    158141  struct Settings { 
    159     float speed, damage, aim, momentum; 
    160     int lifetime; 
    161     bool linger; 
    162     bool punchthrough; 
     142    float speed, aim, momentum; 
     143    int damage, lifetime; 
     144    bool linger, punchthrough, retarget; 
    163145  } 
    164146  Settings settings; 
    165   mixin This!("settings, targets, super(onDeath, x, y, radius=3, life=10) 
    166   #fx=cast(float)x; #fy=cast(float)y; #life=settings.damage; "); 
     147  mixin This!("settings, targets, super(onDeath, pos, radius=3, life=10) 
     148    #life=settings.damage; #delta=vec2f(0); "); 
    167149  LivingThing enemy; 
    168150  void draw() { 
    169151    //line(x, y, enemy.x, enemy.y, White); 
    170     bufferedCircle(x, y, radius, Fill=Black); 
     152    bufferedCircle(pos.to!(int).tuple, radius, Fill=Black); 
    171153  } 
    172154  void damage(typeof(life) d) { 
    173155    super.damage(d); 
    174     if (life!>0) addEffect!(RingEffect)(Red, x, y, 3, 3); 
     156    if (life!>0) addEffect!(RingEffect)(Red, pos, 3, 3); 
    175157  } 
    176158  void hit(LivingThing target) { 
     
    183165    damage(settings.damage/settings.lifetime); 
    184166    if (enemy && enemy.life!>0) enemy=null; // This enemy is ded. 
    185     if (!enemy) enemy=targets.getTarget(this); 
    186     if (!enemy && !settings.linger) { damage(life); onDeath(this); return; } // The war is over. Let's hang around. 
    187     float ndx, ndy; 
     167    if (!enemy) { 
     168      if (!settings.retarget) { die(); return; } 
     169      else { 
     170        enemy=targets.getTarget(this); 
     171        if (!enemy && !settings.linger) { die(); return; } 
     172      } 
     173    } 
     174    vec2f new_motion; 
    188175    if (enemy) { 
    189       ndx=enemy.x-fx; 
    190       ndy=enemy.y-fy; 
    191       normalize(ndx, ndy, 1f-settings.aim); 
     176      new_motion = (enemy.pos - pos).normalized() * (1f - settings.aim); 
    192177      if (auto mt=cast(MovingThing) enemy) { 
    193         float mx, my; mt.getMotionVector(mx, my); 
    194         normalize(mx, my, settings.aim); 
    195         ndx+=mx; ndy+=my; 
     178        new_motion += mt.getMotionVector().normalized() * settings.aim; 
    196179      } 
    197       normalize(ndx, ndy, settings.speed); 
    198     } else ndx=ndy=0; 
    199     dx=dx*settings.momentum+ndx*(1f-settings.momentum); 
    200     dy=dy*settings.momentum+ndy*(1f-settings.momentum); 
    201     fx+=dx; fy+=dy; 
    202     x=cast(int) fx; y=cast(int) fy; 
     180      new_motion.length = settings.speed; 
     181    } else new_motion = vec2f(0f, 0f); 
     182    delta *= settings.momentum; delta += new_motion * (1f - settings.momentum); 
     183    pos += delta; 
    203184    if (enemy && collide(enemy)) { hit(enemy); return; } 
    204185    // if we accidentally hit one of the other targets, we settle for that. 
     
    284265  } 
    285266  Group!(Rocket) rockets; 
    286   mixin This!("settings, rsettings, targets, super(x, y, radius=12), #counter=settings.rate; #rockets=new Group!(Rocket); "); 
     267  mixin This!("settings, rsettings, targets, super(pos, radius=12), 
     268    #counter=settings.rate > 0 ? settings.rate : 1; #rockets=new Group!(Rocket);"); 
    287269  void draw() { 
     270    auto ipos = pos.to!(int); 
    288271    if (mouseOver(this)) { 
    289       circle(x, y, settings.range+1, White); 
    290       circle(x, y, settings.range, Black); 
    291       circle(x, y, settings.range-1, White); 
    292     } 
    293     bufferedCircle(x, y, radius, Black, Fill=White~Green); 
     272      circle(ipos.tuple, settings.range+1, White); 
     273      circle(ipos.tuple, settings.range, Black); 
     274      circle(ipos.tuple, settings.range-1, White); 
     275    } 
     276    bufferedCircle(ipos.tuple, radius, Black, Fill=White~Green); 
    294277    rockets.draw; 
    295278  } 
     
    302285    if (!enemy) return; 
    303286    if (counter-->0) return; 
    304     counter=settings.rate; 
    305     auto newThing=new Rocket(rsettings, targets, &die, x, y); 
    306     if (settings.kickstart) { 
    307       newThing.dx=randf-0.5; 
    308       newThing.dy=randf-0.5; 
    309     } 
    310     newThing.enemy=enemy; 
    311     rockets.addThing(newThing); newThing.update; 
    312   } 
    313 
    314  
     287    counter = settings.rate > 0 ? settings.rate : 1; 
     288    int times = 1; 
     289    if (settings.rate < 0) times = abs(settings.rate); 
     290    Range[times].each = { 
     291      auto newThing=new Rocket(rsettings, targets, &die, pos); 
     292      if (settings.kickstart) newThing.delta = vec2f.rand() / 2f; 
     293      newThing.enemy=enemy; 
     294      rockets.addThing(newThing); newThing.update; 
     295    }; 
     296  } 
     297
     298 
     299import SDL_ttf; 
    315300class SpawnPoint : WorldThing { 
    316301  private { 
    317     int rate
    318     int counter
    319     int life; 
     302    int rate, counter, groupsize, group_left, breaktime, break_left
     303    float life
     304    bool break_mode; 
    320305    Path path; 
    321306  } 
    322307  TargetGroup critters; 
    323   mixin This!("rate, path, super(x, y, radius=15), #counter=0; #critters=new TargetGroup; #life=10; "); 
    324   void draw() { bufferedCircle(x, y, radius, White, Fill=Background~Black); critters.draw; } 
     308  mixin This!("rate, groupsize, breaktime, life, path, super(pos, radius=15), #counter=0; 
     309    #group_left=groupsize; #critters=new TargetGroup; #break_mode=true; #break_left=breaktime; "); 
     310  void draw() { 
     311    bufferedCircle(pos.to!(int).tuple, radius, White, Fill=Background~Black); 
     312    string text; 
     313    if (break_mode) 
     314      if (critters.live) text = ".."; 
     315      else if (break_left) text = Format("-", break_left); 
     316      else text = Format("GO"); 
     317    else if (group_left) text = Format(group_left); 
     318    .print(pos.to!(int).tuple, Center, Black, text); 
     319    critters.draw; 
     320  } 
    325321  void win() { throw new Exception("The critters win!"); } 
    326322  static long id=0; 
    327323  void update() { 
    328     if (counter-->0) { critters.update; return; } 
    329     counter+=rate; 
    330     life *= 1.1; 
    331     auto newCritter=new Critter(path, 0.6, &win, id++, &critters.removeAs!(LivingThing), x, y, 10, life); 
     324    critters.update; 
     325    if (counter > 0) { counter --; return; } 
     326    else counter = rate; 
     327    if (break_mode) { 
     328      if (critters.live) return; 
     329      else if (!break_left) 
     330        break_mode = false; 
     331      else { break_left --; return; } 
     332    } 
     333    if (!group_left) { 
     334      group_left = groupsize; 
     335      if (breaktime) { 
     336        break_mode = true; 
     337        break_left = breaktime; 
     338      } 
     339      life = life * 1.1 + 1; 
     340    } else group_left --; 
     341    // yes the last critter is intentionally stronger. 
     342    auto newCritter=new Critter(path, 0.6, &win, id++, &critters.removeAs!(LivingThing), pos, 10, cast(int) life); 
    332343    critters.addThing(newCritter); newCritter.update; 
    333     critters.update; 
    334344  } 
    335345} 
     
    340350  float count; 
    341351  rgb color; 
    342   mixin This!("color, super(onDeath, x, y, radius=3, life=8) #count=cast(float)0; "); 
     352  mixin This!("color, super(onDeath, pos, radius=3, life=8) #count=cast(float)0; "); 
    343353  void draw() { 
    344     circle(x, y, cast(int)(radius+count+1), color~Yellow); 
    345     circle(x, y, cast(int)(radius+count), color); 
     354    auto ipos = pos.to!(int); 
     355    circle(ipos.tuple, cast(int)(radius+count+1), color~Yellow); 
     356    circle(ipos.tuple, cast(int)(radius+count), color); 
    346357    const int lines=6; 
    347358    for (int i=0; i<360; i+=360/lines) { 
    348359      line( 
    349         cast(int)(x+sin(i*pi180)*(radius+count)), cast(int)(y+cos(i*pi180)*(radius+count)), 
    350         cast(int)(x+sin(i*pi180)*(radius+count+4)), cast(int)(y+cos(i*pi180)*(radius+count+4)), 
     360        cast(int)(pos.x+sin(i*pi180)*(radius+count)), cast(int)(pos.y+cos(i*pi180)*(radius+count)), 
     361        cast(int)(pos.x+sin(i*pi180)*(radius+count+4)), cast(int)(pos.y+cos(i*pi180)*(radius+count+4)), 
    351362        color); 
    352363    } 
     
    394405bool delegate(WorldThing) mouseOver; 
    395406 
     407import test13, tools.functional; 
    396408void main() { 
    397   int mousex, mousey
    398   int startx, starty; bool drag=false; 
     409  vec2f mouse_pos, start
     410  bool drag=false; 
    399411  bool[int] pressed; 
    400412  WorldThing[] select; 
    401413  auto moveMouseOver=(WorldThing w) { 
    402414    foreach (s; select) if (w is s) return true; 
    403     with (w) return (.distance(x, y, mousex, mousey)<=radius); 
     415    with (w) return ((pos - mouse_pos).length()<=radius); 
    404416  }; 
    405417  auto dragMouseOver=(WorldThing wt) { 
    406418    if (SDLKey.LCtrl in pressed) foreach (s; select) if (wt is s) return true; 
    407419    with (wt) { 
    408       if (x+radius<min(startx, mousex)) return false; 
    409       if (x-radius>max(startx, mousex)) return false; 
    410       if (y+radius<min(starty, mousey)) return false; 
    411       if (y-radius>max(starty, mousey)) return false; 
     420      if (pos.x+radius<min(start.x, mouse_pos.x)) return false; 
     421      if (pos.x-radius>max(start.x, mouse_pos.x)) return false; 
     422      if (pos.y+radius<min(start.y, mouse_pos.y)) return false; 
     423      if (pos.y-radius>max(start.y, mouse_pos.y)) return false; 
    412424    } 
    413425    return true; 
     
    419431  Group!(Thing) group; 
    420432  auto path=new Path(false, 
    421     Path.Point(30, 30), Path.Point(300, 30), Path.Point(300, 300), Path.Point(30, 300), Path.Point(30, 30) 
     433    vec2f(30, 30), vec2f(300, 30), vec2f(300, 300), vec2f(30, 300), vec2f(30, 90) 
    422434  ); 
    423   auto spawner=new SpawnPoint(64, path, 300, 400); 
     435   
     436  auto bg_surf = screen.With(screen.w, screen.h) = { 
     437    FatLine fl; 
     438    fl = new FatLine(vec2f(300, 400) ~ path.points, (float d) { 
     439      if (abs(d) > fl.width) return Background; 
     440      else if (abs(d) > fl.width - 2) return Background.blend(Black, (fl.width - abs(d)) / 2f); 
     441      else if (abs(d) > fl.width - 4) return Black.blend(White, (fl.width - 2 - abs(d)) / 2f); 
     442      else return White; 
     443    }, 18); 
     444    fl.render(); 
     445  }; 
     446   
     447  auto spawner=new SpawnPoint(/* rate */ 48, /* groupsize */ 10, /* breaktime */ 5, /* start life */ 64, path, vec2f(300, 400)); 
    424448  group=new typeof(group)([cast(Thing)spawner]); 
    425449  group.addThing(new Turret( 
    426     Turret.Settings(115, 1, true), 
    427     Rocket.Settings(/*speed*/ 1f, /*damage*/ 20, /*aim*/ 0.45, /*momentum*/0.99, /*lifetime*/1000, false, false), 
    428     spawner.critters, 50, 250 
     450    Turret.Settings(115, 2, false), 
     451    Rocket.Settings(/*speed*/ 1.1f, /*aim*/ 0.1, /*momentum*/0.97, /*damage*/ 1, /*lifetime*/256, /*linger*/false, /*punchthrough*/false), 
     452    spawner.critters, vec2f(85, 220) 
     453  )); 
     454  group.addThing(new Turret( 
     455    Turret.Settings(115, 2, false), 
     456    Rocket.Settings(/*speed*/ 1.1f, /*aim*/ 0.1, /*momentum*/0.97, /*damage*/ 1, /*lifetime*/256, false, false), 
     457    spawner.critters, vec2f(185, 135) 
    429458  )); 
    430459  group.addThing(effects); 
     
    438467    update; 
    439468    // addEffect!(RingEffect)(Blue~Black, mousex, mousey, 50, 50); 
     469    display.blit(bg_surf); 
     470    prettyprint(0, 0, Bottom|Right, 
     471      "Test .. test! [b]Bold, [i]italic and [u]underlined![/u][/i][/b] [i]Just italic now.[/i] [b][color #f00]Red?[/color][/b]Done!"); 
    440472    draw; 
    441473    if (drag) { 
    442       tintfill(min(startx, mousex), min(starty, mousey), max(startx, mousex), max(starty, mousey), Blue~White); 
    443       line(startx, starty, mousex, mousey, Box=White); 
     474      tintfill(start.min(mouse_pos).to!(int).tuple, start.max(mouse_pos).to!(int).tuple, Blue~White); 
     475      line(start.to!(int).tuple, mouse_pos.to!(int).tuple, Box=White); 
    444476    } 
    445477    limiter.limit({ flip; }); 
     
    451483    }, (int x, int y, ubyte button, int p) { 
    452484      if (!button) { 
    453         mousex=x; mousey=y; 
     485        mouse_pos.x=x; mouse_pos.y=y; 
    454486      } else { 
    455487        if (p==1) { 
    456           startx=x; starty=y; 
     488          start.x=x; start.y=y; 
    457489          mouseOver=dragMouseOver; 
    458490          drag=true; 
     
    476508      fps=0; 
    477509    } 
    478     with (Background) SDL_FillRect(display.surface, null, SDL_MapRGBA(display.surface.format, values[0], values[1], values[2], 0)); 
     510    // with (Background) SDL_FillRect(display.surface, null, SDL_MapRGBA(display.surface.format, values[0], values[1], values[2], 0)); 
    479511  } while (true); 
    480512} 
  • trunk/qd/qd.d

    r320 r343  
    173173    struct { ubyte r, g, b; } 
    174174  } 
     175  SDL_Color toSDL() { return SDL_Color(r, g, b, 0); } 
    175176  rgb opCat(rgb other) { 
    176177    rgb res; 
     
    553554    int height() { return display.height; } 
    554555    alias width w; alias height h; 
    555     Area With(size_t w, size_t h, void delegate()[] dgs...) { 
    556       auto backup=display, backup_flags=sdl_flags, old_osc=offscreen; 
    557       scope(exit) { display=backup; sdl_flags=backup_flags; offscreen=old_osc; } 
    558       screen(w, h, 0, true); 
    559       foreach (dg; dgs) dg(); 
    560       return display; 
    561     } 
    562     void With(Area area, void delegate()[] dgs...) { 
    563       auto backup=display; display=area; scope(exit) display=backup; 
    564       auto backup_flags=sdl_flags; scope(exit) sdl_flags=backup_flags; 
    565       auto offs=offscreen; scope(exit) offscreen=offs; 
    566       foreach (dg; dgs) dg(); 
     556    struct WithAreaHolder(T...) { 
     557      T t; 
     558      Area opAssign(C)(lazy C callable) { 
     559        static if (is(T == Tuple!(Area))) { 
     560          auto backup=display; display=t[0]; scope(exit) display=backup; 
     561          auto backup_flags=sdl_flags; scope(exit) sdl_flags=backup_flags; 
     562          auto offs=offscreen; scope(exit) offscreen=offs; 
     563        } else static if (is(T == Tuple!(int, int))) { 
     564          auto backup=display, backup_flags=sdl_flags, old_osc=offscreen; 
     565          scope(exit) { display=backup; sdl_flags=backup_flags; offscreen=old_osc; } 
     566          screen(w, h, 0, true); 
     567        } else static assert(false, "opAssign with "~T.stringof~" .. ?"); 
     568        static if (is(C==void)) callable(); 
     569        else static if (is(C==void delegate())) callable()(); 
     570        else static assert(false, "Cannot call: "~T.stringof); 
     571        return display; 
     572      } 
     573    } 
     574    WithAreaHolder!(T) With(T...)(T t) { 
     575      WithAreaHolder!(T) res = void; 
     576      foreach (id, value; t) res.t[id] = value; 
     577      return res; 
    567578    } 
    568579  } 
     
    704715  } 
    705716  Area width(int w) { 
    706     if (w<0) return Area(br-pt(-w, height), pt(-w, size.y), surface); 
    707     return Area(tl, pt(w, size.y), surface); 
     717    if (w<0) { 
     718      auto new_size = pt(-w, size.y); 
     719      tl = br - pt(-w, height); 
     720      dimensions = new_size; 
     721      return this; 
     722    } else { 
     723      dimensions = pt(w, size.y); 
     724      return this; 
     725    } 
    708726  } 
    709727  //Area width(float wp) { return width(cast(int)(width*wp)); } 
    710728  int width() { return dimensions.x; } 
    711729  Area height(int h) { 
    712     if (h<0) return Area(br-pt(width, -h), pt(size.x, -h), surface); 
    713     return Area(tl, pt(size.x, h), surface); 
     730    if (h<0) { 
     731      auto new_size = pt(size.x, -h); 
     732      tl = br - pt(width, -h); 
     733      dimensions = new_size; 
     734      return this; 
     735    } else { 
     736      dimensions = pt(size.x, h); 
     737      return this; 
     738    } 
    714739  } 
    715740  //Area height(float hp) { return height(cast(int)(height*hp)); } 
     
    723748    return Area(tl3, size, surface); 
    724749  } 
    725   Area select(pt size, pt where, Align how) { 
     750  Area select(pt where, pt size, Align how) { 
    726751    return Area(tl+where+pt([-size.x/2, -size.x, 0][how&3], [-size.y/2, -size.y, 0][how>>2]), size, surface); 
    727752  } 
  • trunk/qd/test11.d

    r320 r343  
    1818      Box=White, Fill=Black.blend(White, 0.1).blend(Black.blend(target, 0.9), p/50f) 
    1919    ); 
    20     print(button, Center, Format("Hello World")); 
     20    print(button, Center, White, Format("Hello World")); 
    2121  }; 
    2222  while (true) { 
  • trunk/qd/test13.d

    r342 r343  
    11module test13; 
    22 
    3 import qd, dglut.vector, std.stdio, tools.base, tools.log
     3import qd, dglut.vector, std.stdio, tools.base, tools.log, std.math
    44 
    55bool _polygons_overlap_4(vec2f[4] poly_1, vec2f[4] poly_2) { 
     
    3030  vec2f[] pts, ds, vs; 
    3131  float width; 
    32   this(vec2f[] pts, float w) { 
     32  this(vec2f[] pts, typeof(color) c, float w) { 
     33    color = c; 
    3334    width = w; 
    3435    this.pts = pts.dup; 
     
    7475  } 
    7576  alias normal_dist opCall; 
     77  rgb delegate(float) color; 
     78  void fill_quad(vec2f tl, vec2f br) { 
     79    for (int x = cast(int) tl.x; x < br.x; ++x) 
     80      for (int y = cast(int) tl.y; y < br.y; ++y) 
     81        pset(x, y, color(opCall(vec2f(x, y)))); 
     82  } 
     83  const MAXSIZE = 4; 
     84  void quad_descent(vec2f tl, vec2f br, float[4] dists = [float.nan, 0f, 0f, 0f]) { 
     85    bool maxdepth = ((br.x-tl.x) < MAXSIZE) || ((br.y-tl.y) < MAXSIZE); 
     86    if (isnan(dists[0])) { 
     87      dists[] = [opCall(tl), opCall(vec2f(br.x, tl.y)), opCall(vec2f(tl.x, br.y)), opCall(br)]; 
     88    } 
     89    void try_desc(vec2f new_tl, vec2f new_br, float[4] dists) { 
     90      if (!overlap(new_tl, new_br)) { 
     91        line(new_tl.tuple, new_br.tuple, Fill=color(dists[0])/+, Box=Blue+/); 
     92        return; 
     93      } 
     94      if (maxdepth) fill_quad(new_tl, new_br); 
     95      else quad_descent(new_tl, new_br, dists); 
     96    } 
     97    if (maxdepth) fill_quad(tl, br); 
     98    else { 
     99      auto half = (tl + br) / 2; 
     100      auto new_dists = [opCall(vec2f(half.x, tl.y)), opCall(vec2f(tl.x, half.y)), opCall(vec2f(br.x, half.y)), opCall(vec2f(half.x, br.y))]; 
     101      auto center = opCall(half); 
     102      try_desc(tl, half, [dists[0], new_dists[0], new_dists[1], center]); 
     103      try_desc(vec2f(half.x, tl.y), vec2f(br.x, half.y), [new_dists[0], dists[1], center, new_dists[2]]); 
     104      try_desc(vec2f(tl.x, half.y), vec2f(half.x, br.y), [new_dists[1], center, dists[2], new_dists[3]]); 
     105      try_desc(half, br, [center, new_dists[2], new_dists[3], dists[3]]); 
     106    } 
     107  } 
     108  void render() { 
     109    quad_descent(vec2f(0, 0), vec2f(screen.w, screen.h)); 
     110  } 
    76111} 
    77112 
     
    86121} 
    87122 
    88 import tools.functional, std.math, tools.mersenne; 
     123/*import tools.functional, std.math, tools.mersenne; 
    89124void main() { 
    90125  screen(1024, 768); 
     
    108143    else return White; 
    109144  } 
    110   void fill_quad(vec2f tl, vec2f br) { 
    111     for (int x = cast(int) tl.x; x < br.x; ++x) 
    112       for (int y = cast(int) tl.y; y < br.y; ++y) 
    113         pset(x, y, color(df(vec2f(x, y)))); 
    114   } 
    115   const MAXSIZE = 4; 
    116   void quad_descent(vec2f tl, vec2f br, float[4] dists = [float.nan, 0f, 0f, 0f]) { 
    117     bool maxdepth = ((br.x-tl.x) < MAXSIZE) || ((br.y-tl.y) < MAXSIZE); 
    118     if (isnan(dists[0])) { 
    119       dists[] = [df(tl), df(vec2f(br.x, tl.y)), df(vec2f(tl.x, br.y)), df(br)]; 
    120     } 
    121     void try_desc(vec2f new_tl, vec2f new_br, float[4] dists) { 
    122       if (!df.overlap(new_tl, new_br)) { 
    123         line(new_tl.tuple, new_br.tuple, Fill=color(dists[0])/*, Box=Blue*/); 
    124         return; 
    125       } 
    126       if (maxdepth) fill_quad(new_tl, new_br); 
    127       else quad_descent(new_tl, new_br, dists); 
    128     } 
    129     if (maxdepth) fill_quad(tl, br); 
    130     else { 
    131       auto half = (tl + br) / 2; 
    132       auto new_dists = [df(vec2f(half.x, tl.y)), df(vec2f(tl.x, half.y)), df(vec2f(br.x, half.y)), df(vec2f(half.x, br.y))]; 
    133       auto center = df(half); 
    134       try_desc(tl, half, [dists[0], new_dists[0], new_dists[1], center]); 
    135       try_desc(vec2f(half.x, tl.y), vec2f(br.x, half.y), [new_dists[0], dists[1], center, new_dists[2]]); 
    136       try_desc(vec2f(tl.x, half.y), vec2f(half.x, br.y), [new_dists[1], center, dists[2], new_dists[3]]); 
    137       try_desc(half, br, [center, new_dists[2], new_dists[3], dists[3]]); 
    138     } 
    139   } 
    140145  while (true) { 
    141146    quad_descent(vec2f(0, 0), vec2f(screen.w, screen.h)); 
     
    147152  } 
    148153} 
     154*/ 
  • trunk/qd/test2.d

    r316 r343  
    2626class Primitives { 
    2727  void drawFrame(ref Area orig) { 
    28     with (orig) screen.With(orig, line(0, 0, (size-pt(1, 1)).tupleof, Box=White)); 
     28    with (orig) screen.With(orig) = line(0, 0, (size-pt(1, 1)).tupleof, Box=White); 
    2929    orig=orig.shrink(1); 
    3030  } 
     
    201201    logln("render proc - temp=", temp); 
    202202    assert(drawthr.runsMe()); 
    203     size_t aa=3
     203    size_t aa=1
    204204    float scale = 255f / (aa*aa); 
    205205    size_t cc=0; 
     
    260260  void area(Area target) { 
    261261    if (target && (!myArea || target.dimensions!=myArea.dimensions)) { 
    262       temp = screen.With(target.width, target.height, cls)
     262      temp = screen.With(target.width, target.height) = cls
    263263    } 
    264264    super.area=target; 
     
    498498class TextBox : Text { 
    499499  this(string s, Align alignment=Left|Top) { super(s, alignment); } 
    500   void draw() { screen.With(myArea, cls); super.draw(); } 
     500  void draw() { screen.With(myArea) = cls; super.draw(); } 
    501501} 
    502502