WIP (Threaded Rendering, CP-Lock, MultiDisplay)

graphics
Harald Christian Joachim Wolff 2017-05-26 15:12:22 +02:00
parent 634da6fe0b
commit dd4dc701f9
38 changed files with 1196 additions and 382 deletions

View File

@ -18,85 +18,77 @@ using org.budnhead.core;
namespace bnhdemo
{
public class BootStrap
public static class BootStrap
{
public static BootStrap _instance;
public static BootStrap instance()
{
return _instance;
}
static SquaredMap map;
OpenGLWindow glWindow;
SquaredMap map;
static Actor trackedActor;
static GLCamera trackingCamera;
public static void Main(string[] args){
_instance = new BootStrap();
Engine.InitializeGraphics();
_instance.run();
Engine.SceneWindows[0].Scene = new Scene();
loadMap();
Engine.SceneWindows[0].Visible = true;
Engine.SceneWindows[0].KeyPress += (sender, e) => {
switch (e.KeyChar){
case 'r':
SceneWindow sw = Engine.createSceneWindow();
sw.Visible = true;
sw.Scene = new Scene(Engine.SceneWindows[0].Scene);
GLCamera cam = new GLCamera();
cam.Position = new Vector3(800,800,384);
cam.View = new Vector3(-1,-1,-1);
cam.Top = Vector3.UnitZ;
CameraRotator cr = new CameraRotator(cam);
sw.PrimaryViewport.SceneOrientation = cam;
trackingCamera = cam;
break;
case ' ':
Console.WriteLine("Fire Ballistic...");
BallisticActor ba = new BallisticActor(0);
ba.Position.Value = map.ground(new Vector2(10,10));
ba.Velocity.Value = new Vector3(1,1,1).Normalized();
ba.Velocity.Value *= 100.0f;
ba.fire();
trackedActor = ba;
break;
}
};
Engine.AfterUpdate += delegate {
if ((trackedActor != null)&&(trackingCamera != null)){
if (trackedActor.IsActive){
trackingCamera.lookAt(trackedActor.Position.Value);
} else {
trackedActor = null;
}
}
};
Engine.run();
}
public BootStrap()
{
bootGraphics();
bootAudio();
bootMap();
}
public SquaredMap SquaredMap {
get { return this.map; }
}
public void bootGraphics(){
glWindow = new OpenGLWindow();
glWindow.MakeCurrent();
GlobalDefaults.instance();
}
public void bootAudio(){
AudioDelegate.init();
AudioDelegate.DistanceModel("exponential", true);
nhBuffers.addSearchPath("./sounds");
nhBuffers.loadSound("HowFire", "HowHit", "st1");
//AudioDelegate.test();
}
public void bootMap(){
public static void loadMap(){
ImageSharp.Image i = ImageSharp.Image.Load( new FileStream("M3-wip.png",FileMode.Open));
i.Flip(ImageSharp.Processing.FlipType.Vertical);
i.Resize(500,500);
map = new SquaredMap(i);
glWindow.Scene.RootObject.addChild( map );
ModelManager.instance.addSearchPath("./models");
DumpObject dobj = new DumpObject();
dobj.Model3D = ModelManager.instance.loadModel("alfa147",0.0254f);
Vector3 v3 = map.ground(new Vector2(24,24));
dobj.Position = v3;
glWindow.Scene.RootObject.addChild( dobj );
}
public void run(){
glWindow.MakeCurrent();
glWindow.Run(25,25);
Engine.SceneWindows[0].Scene.RootObject.addChild(map);
}
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.IO;
using OpenTK.Graphics.OpenGL;
using OpenTK;
namespace bnhdemo
{
public class Graphics
{
private TextureManager textureManager;
public Graphics()
{
this.textureManager = new TextureManager();
}
TextureManager TextureManager {
get { return this.textureManager; }
}
}
}

View File

@ -60,9 +60,8 @@
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="BootStrap.cs" />
<Compile Include="Graphics.cs" />
<Compile Include="OpenGLWindow.cs" />
<Compile Include="TextureManager.cs" />
<Compile Include="demo\CameraRotator.cs" />
</ItemGroup>
<ItemGroup>
<None Include="OpenTK.dll.config">
@ -114,6 +113,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="sounds\" />
<Folder Include="demo\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,34 @@
using System;
using OpenTK;
using org.budnhead.core;
using org.budnhead.graphics;
namespace bnhdemo
{
public class CameraRotator : Actor
{
GLCamera camera;
Matrix3 m3 = Matrix3.CreateRotationZ(MathHelper.PiOver2 / 45.0f);
Vector3 p = new Vector3(400,400,256);
Vector3 offset = new Vector3(150,0,0);
Vector3 view = new Vector3(-1,0,-1);
public CameraRotator(GLCamera camera)
:base(0)
{
this.camera = camera;
}
public override void update(float timespan)
{
offset = m3 * offset;
view = m3 * view;
camera.Position = p + offset;
camera.View = view.Normalized();
}
}
}

View File

@ -10,25 +10,20 @@ namespace org.budnhead.core
{
public class Actor : WorldObject
{
public static List<Actor> activeActors = new List<Actor>();
public static List<Actor> finishedActors = new List<Actor>();
internal static List<Actor> activeActors = new List<Actor>();
private static List<Actor> finishedActors = new List<Actor>();
public static void updateAll(float timespan)
{
foreach (Actor a in activeActors)
{
a.update(timespan);
internal static void updateActors(float elapsed){
// Update all active Actors...
foreach (Actor a in activeActors.ToArray()){
a.update(elapsed);
}
foreach (Actor a in finishedActors)
{
// Remove finished Actors
foreach (Actor a in finishedActors.ToArray()){
activeActors.Remove(a);
}
finishedActors.Clear();
}
private int id;
@ -39,26 +34,30 @@ namespace org.budnhead.core
this.id = id;
activeActors.Add(this);
_player = new nhPlayer();
activePlayers.Add(_player);
//_player = new nhPlayer();
//activePlayers.Add(_player);
}
public void destroy(){
finishedActors.Add(this);
_player.deletePlayer();
//_player.deletePlayer();
}
public Vector3 Heading { get; set; }
public Vector3 Velocity { get; set; }
public float Weight { get; set; }
public readonly BufferedValueInstance<Vector3> Heading = new BufferedValueInstance<Vector3>(new Vector3(0,0,1));
public readonly BufferedValueInstance<Vector3> Velocity = new BufferedValueInstance<Vector3>(new Vector3());
public readonly BufferedValueInstance<float> Weight = new BufferedValueInstance<float>(0);
public bool IsActive {
get { return activeActors.Contains(this); }
}
public virtual void update(float timespan){
if (soundPlaying()){
/* if (soundPlaying()){
syncSoundPosition();
}
}
*/ }
public void setHeading(Vector3 heading,Vector3 top){
Vector3 x,y,z;
@ -74,7 +73,7 @@ namespace org.budnhead.core
new Vector4(0,0,0,1)
);
Rotation = Matrix4.CreateRotationX(MathHelper.PiOver2) * mRotation;
Rotation.Value = Matrix4.CreateRotationX(MathHelper.PiOver2) * mRotation;
}
public Model3D Model3D { get; set; }
@ -99,35 +98,34 @@ namespace org.budnhead.core
public void setDistanceAttenuation(float rollOf = 2.0f, float refDistance = 1.0f, float maxDistance = 100.0f)
{
_player.setDistanceAttenuation(rollOf, refDistance, maxDistance);
// _player.setDistanceAttenuation(rollOf, refDistance, maxDistance);
}
public void setBuffers(params string[] buffers)
{
foreach (string i in buffers)
/* foreach (string i in buffers)
{
if(!aBuffers.ContainsKey(i))
aBuffers.Add(i, nhBuffers.buffers[i]);
}
}*/
}
public void playSound(string sound, float gain = 1.0f, bool loop = false)
{
_player.position = this.Position;
_player.velocity = this.Velocity;
_player.play(aBuffers[sound], gain, loop);
// _player.position = this.Position.Value;
// _player.velocity = this.Velocity.Value;
// _player.play(aBuffers[sound], gain, loop);
}
private void syncSoundPosition()
{
_player.setPosition(this.Position);
_player.setVelocity(this.Velocity);
// _player.setPosition(this.Position.Value);
// _player.setVelocity(this.Velocity.Value);
}
public Boolean soundPlaying(){
return _player.state();
return false; //_player.state();
}
}

View File

@ -2,6 +2,7 @@
using org.budnhead.graphics.primitives;
using org.budnhead.graphics;
using org.budnhead.exceptions;
using org.budnhead.tools;
using OpenTK;
@ -17,7 +18,7 @@ namespace org.budnhead.core
:base(id)
{
this.actorState = BallisticActorStates.FLYING;
this.Model3D = ModelManager.instance.findModel("ballistisch");
this.Model3D = ResourceLibrary.getResource<LoadedModel>("ballistisch");
for (int n=0;n < this.Model3D.vertexes.Length;n++){
this.Model3D.colors[n] = new Vector4(1.0f,0.2f + (0.5f * this.Model3D.vertexes[n].Z / -4.0f),0,1.0f);
@ -35,16 +36,16 @@ namespace org.budnhead.core
switch (actorState){
case BallisticActorStates.FLYING:
Velocity += (Physics.Gravitation * timespan);
Position += Velocity * timespan;
Velocity.Value += (Physics.Gravitation * timespan);
Position.Value += Velocity.Value * timespan;
setHeading( Velocity, Physics.Gravitation);
setHeading( Velocity.Value, Physics.Gravitation);
try
{
Vector3 ground = SquaredMap.activeMap.ground(Position.Xy);
Vector3 ground = SquaredMap.activeMap.ground(Position.Value.Xy);
if (Position.Z <= ground.Z){
if (Position.Value.Z <= ground.Z){
Console.WriteLine("BallisticActor hit ground!");
actorState = BallisticActorStates.HIT;
playSound("HowHit");
@ -71,7 +72,7 @@ namespace org.budnhead.core
public void fire()
{
playSound("HowFire");
//playSound("HowFire");
}

View File

@ -0,0 +1,61 @@

using System;
using System.Collections.Generic;
namespace org.budnhead
{
public interface IBufferedValue {
void buffer();
object getBufferedValue();
object getValue();
}
public class BufferedValueInstance<T> : IDisposable,IBufferedValue
{
static List<IBufferedValue> bufferedValues = new List<IBufferedValue>();
static public void cycle(){
foreach (IBufferedValue bvi in bufferedValues){
bvi.buffer();
}
}
T value,bufferedValue;
public BufferedValueInstance(){
bufferedValues.Add(this);
}
public BufferedValueInstance(T initialValue){
Value = initialValue;
bufferedValues.Add(this);
}
public T Value {
get { return this.value; }
set { this.value = value; }
}
public T BufferedValue{
get { return this.bufferedValue; }
}
public void Dispose(){
bufferedValues.Remove(this);
}
public void buffer(){
this.bufferedValue = this.value;
}
public object getBufferedValue()
{
return this.bufferedValue;
}
public object getValue()
{
return this.value;
}
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Threading;
namespace org.budnhead
{
/**
* ConsumerProducerLock
*
* Lock a Resource for one producer, mutliple consumers (read-only)
*
* Producer Lock: Producer will receive and hold lock if no other producer is active
* Producer Exclusive Lock: Producer will receive and hold lock, while no consumers are active
* Consumer Lock: Consumers will get lock while no Producer Exclusive Lock is held
*
**/
public class ConsumerProducerLock
{
Object producer;
Object producerExclusiveLock;
Object consumerLock;
Int32 consumers;
bool producerIsExclusive;
public ConsumerProducerLock(){
producer = new object();
producerExclusiveLock = new object();
consumerLock = new object();
consumers = 0;
}
public void ConsumerEnter(){
Monitor.Enter(producerExclusiveLock);
Monitor.Enter(consumerLock);
consumers ++;
Monitor.Exit(consumerLock);
Monitor.Exit(producerExclusiveLock);
}
public void ConsumerExit(){
Monitor.Enter(producerExclusiveLock);
Monitor.Enter(consumerLock);
consumers --;
if (consumers == 0){
Monitor.Pulse(producerExclusiveLock);
}
Monitor.Exit(consumerLock);
Monitor.Exit(producerExclusiveLock);
}
public void ProducerEnter(){
Monitor.Enter(producer);
}
public void ProducerExit(){
Monitor.Exit(producer);
if (Monitor.IsEntered(producerExclusiveLock)){
Monitor.Exit(producerExclusiveLock);
}
}
public void producerExclusive(){
Monitor.Enter(producerExclusiveLock);
if (consumers > 0){
Monitor.Wait(producerExclusiveLock);
}
}
}
}

View File

@ -0,0 +1,174 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
using org.budnhead.graphics;
using org.budnhead.tools;
using OpenTK.Graphics;
namespace org.budnhead.core
{
public delegate void UpdateDelegate(float elapsed);
public static class Engine
{
/** Objects of the Game World **/
/** Engine management stuff **/
private static Object engineLock = new object();
private static Boolean initialized = false;
private static readonly float tickTimeSpan = (1.0f / Stopwatch.Frequency);
private static readonly float tickTimeSpanMS = (1000.0f / Stopwatch.Frequency);
private static long lastWorldUpdateTick;
private static ConsumerProducerLock
consumerProducerLock = new ConsumerProducerLock();
internal static List<SceneWindow>
sceneWindows = new List<SceneWindow>();
private static JobThreader sceneWindowJobs;
private static Thread updateThread = new Thread(updateWorldThread);
public static event UpdateDelegate
BeforeUpdate,
AfterUpdate;
private static Boolean exiting;
private static Object syncGraphicsStartup = new object();
private static float targetUpdatePeriod = 100;
public static SceneWindow[] SceneWindows {
get { lock (sceneWindows) { return sceneWindows.ToArray(); } }
}
public static float TargetUpdatePeriod {
get { return targetUpdatePeriod; }
set { targetUpdatePeriod = value; }
}
public static float TargetUpdateFrequency {
get { return targetUpdatePeriod == 0 ? 0 : 1.0f / targetUpdatePeriod; }
set { targetUpdatePeriod = value == 0 ? 0 : 1.0f / value; }
}
public static Boolean ShouldContinue {
get { lock(engineLock) { return !Engine.exiting; } }
}
public static void Shutdown(){
lock (engineLock){
exiting = true;
}
}
public static void Initialize(){
InitializeGraphics();
InitializeUpdateThread();
}
public static void InitializeUpdateThread(){
}
public static void InitializeGraphics(){
GraphicsContext.ShareContexts = true;
sceneWindowJobs = new JobThreader();
SceneWindow primaryWindow = new SceneWindow();
primaryWindow.MakeCurrent();
initialized = GlobalDefaults.initialize();
}
public static void run(){
updateThread.Start();
sceneWindowsThread();
}
private static void updateWorld(float elapsed){
consumerProducerLock.ProducerEnter();
if (BeforeUpdate!=null){
BeforeUpdate(elapsed);
}
Actor.updateActors(elapsed);
if (AfterUpdate!=null){
AfterUpdate(elapsed);
}
consumerProducerLock.producerExclusive();
cycleBufferedValues();
consumerProducerLock.ProducerExit();
}
public static bool cycleBufferedValues(){
BufferedValueInstance<object>.cycle();
return true;
}
public static void ConsumerEnter(){
consumerProducerLock.ConsumerEnter();
}
public static void ConsumerExit(){
consumerProducerLock.ConsumerExit();
}
public static SceneWindow createSceneWindow(){
return sceneWindowJobs.execute(delegate { return new SceneWindow(); });
}
static void sceneWindowsThread(){
while (Engine.ShouldContinue){
sceneWindowJobs.execute();
lock(Engine.sceneWindows){
foreach (SceneWindow sceneWindow in Engine.sceneWindows.ToArray()){
if (sceneWindow.Visible){
sceneWindow.ProcessEvents();
}
}
foreach (SceneWindow sceneWindow in Engine.sceneWindows.ToArray()){
sceneWindow.paint();
}
}
}
}
static void updateWorldThread(){
long lastWorldUpdateTick = Stopwatch.GetTimestamp();
float elapsed = 0;
float update_needs;
while (Engine.ShouldContinue){
long ticks = Stopwatch.GetTimestamp();
elapsed = tickTimeSpan * (ticks - lastWorldUpdateTick);
updateWorld(elapsed);
update_needs = tickTimeSpanMS * (Stopwatch.GetTimestamp() - ticks);
lastWorldUpdateTick = ticks;
if (update_needs < targetUpdatePeriod){
Thread.Sleep( (int)(targetUpdatePeriod - update_needs) );
}
}
}
}
}

View File

@ -73,8 +73,8 @@ namespace org.budnhead.core
.requires(intersectPlainCoeff(P,V,A,B,C,out coeff))
.requires(coeff.Y >= 0)
.requires(coeff.Z >= 0)
.requires(coeff.Y <= 1)
.requires(coeff.Z <= 1)
.requires(coeff.Y <= 1.00001f)
.requires(coeff.Z <= 1.00001f)
.assigns(ref p, delegate { return P + (coeff.X * V); })
.isSuccess();
}
@ -89,9 +89,9 @@ namespace org.budnhead.core
.requires(intersectPlainCoeff(P,V,A,B,C,out coeff))
.requires(coeff.Y >= 0)
.requires(coeff.Z >= 0)
.requires(coeff.Y <= 1)
.requires(coeff.Z <= 1)
.requires(coeff.Y + coeff.Z <= 1)
.requires(coeff.Y <= 1.00001f)
.requires(coeff.Z <= 1.00001f)
.requires(coeff.Y + coeff.Z <= 1.00001f)
.assigns(ref p, delegate { return A + (coeff.Y * (B-A)) + (coeff.Z * (C-A)); })
.isSuccess();
}

View File

@ -2,55 +2,29 @@
using OpenTK.Graphics.OpenGL;
namespace org.budnhead.graphics
using org.budnhead.graphics;
using org.budnhead.tools;
namespace org.budnhead.core
{
public class GlobalDefaults
public static class GlobalDefaults
{
private static GlobalDefaults _instance = new GlobalDefaults();
public static GlobalDefaults instance(){
return _instance;
}
internal static bool initialize(){
ResourceLibrary.initializeResourceType(typeof(Shader), "shader/", "");
ResourceLibrary.initializeResourceType(typeof(ShaderProgram), "shader/", ".program");
ResourceLibrary.initializeResourceType(typeof(LoadedModel), "models/", ".obj");
private Shader defVertexShader,
defFragmentShader;
private ShaderProgram
defShaderProgram;
ResourceLibrary.cacheInstance("default.vshader",new Shader(OpenTK.Graphics.OpenGL.ShaderType.VertexShader, defVertexShaderSource));
ResourceLibrary.cacheInstance("default.fshader",new Shader(OpenTK.Graphics.OpenGL.ShaderType.FragmentShader, defFragmentShaderSource));
private GLSceneOrientation activeScene;
ResourceLibrary.cacheInstance("default",new ShaderProgram("default.vshader","default.fshader"));
private GlobalDefaults(){
Console.WriteLine("GlobalDefaults: Shader Version: {0}", GL.GetString(StringName.ShadingLanguageVersion));
defVertexShader = new Shader(OpenTK.Graphics.OpenGL.ShaderType.VertexShader, defVertexShaderSource);
defFragmentShader = new Shader(OpenTK.Graphics.OpenGL.ShaderType.FragmentShader, defFragmentShaderSource);
defShaderProgram = new ShaderProgram(defVertexShader, defFragmentShader);
activeScene = new GLSceneOrientation();
}
public ShaderProgram DefaultShaderProgram {
get { return this.defShaderProgram;}
}
public Shader DefaultVertexShader
{
get { return defVertexShader; }
}
public Shader DefaultFragmentShader
{
get { return defFragmentShader; }
}
public GLSceneOrientation ActiveScene {
get { return this.activeScene; }
set { this.activeScene = value; }
return true;
}
private string defVertexShaderSource = @"#version 330
private static string defVertexShaderSource = @"#version 330
layout(location = 0) in vec3 iv_position;
layout(location = 1) in vec4 iv_color;
@ -94,7 +68,7 @@ void main()
";
private string defFragmentShaderSource = @"#version 330
private static string defFragmentShaderSource = @"#version 330
in vec4 color;
in vec3 norm;
@ -119,7 +93,5 @@ void main()
";
}
}

View File

@ -13,8 +13,8 @@ namespace org.budnhead.core
rows[2] = new Vector4(X.Z,Y.Z,Z.Z,W.Z);
c = new Vector3();
Console.WriteLine("New Linear Equation System to solve:");
dumpLinearSystem(rows);
//Console.WriteLine("New Linear Equation System to solve:");
//dumpLinearSystem(rows);
if (rows[0].Z == 0){
Vector4 t = rows[0];
@ -34,7 +34,7 @@ namespace org.budnhead.core
rows[2] -= rows[0] * (rows[2].Z / rows[0].Z);
}
dumpLinearSystem(rows);
//dumpLinearSystem(rows);
if (rows[1].Y == 0){
Vector4 t = rows[1];
@ -48,7 +48,7 @@ namespace org.budnhead.core
rows[2] -= rows[1] * (rows[2].Y / rows[1].Y);
}
dumpLinearSystem(rows);
//dumpLinearSystem(rows);
rows[2] /= rows[2].X;
c.X = rows[2].W;
@ -65,8 +65,8 @@ namespace org.budnhead.core
rows[0] /= rows[0].Z;
c.Z = rows[0].W;
dumpLinearSystem(rows);
Console.WriteLine("Solved to {0}",c);
//dumpLinearSystem(rows);
//Console.WriteLine("Solved to {0}",c);
return true;
}

View File

@ -9,11 +9,10 @@ using OpenTK.Graphics.OpenGL4;
using OpenTK;
using org.hwo.contracts;
using org.budnhead.core;
using org.budnhead.exceptions;
using org.budnhead.graphics;
namespace org.budnhead.graphics
namespace org.budnhead.core
{
public class SquaredMap : WorldObject
{
@ -197,7 +196,7 @@ namespace org.budnhead.graphics
public Vector2 toTileBorderless(Vector2 world){
Vector2 tile = world / edge;
return tile;
return new Vector2((int)tile.X,(int)tile.Y);
}
public Vector2 toTile(Vector2 world){
@ -211,7 +210,7 @@ namespace org.budnhead.graphics
.requires(tile.Y < height)
.throws<OutOfWorldException>();
return tile;
return new Vector2((int)tile.X,(int)tile.Y);
}
public Vector2 intersectTile(Vector3 P,Vector3 V){
@ -225,57 +224,63 @@ namespace org.budnhead.graphics
Console.WriteLine("P: {0} V: {1}",P,V);
if (!Geometry.intersectPlain(P,V,corners[0],corners[1],corners[3],out A)){
throw new OutOfWorldException();
}
if (!Geometry.intersectPlain(P,V,corners[4],corners[5],corners[7],out B)){
throw new OutOfWorldException();
}
Console.WriteLine("Lower Plane Intersection (LIN): {0}",A);
A = P + ( V * ( -P.Z / V.Z) );
Console.WriteLine("Lower Plane Intersection: {0}",A);
Console.WriteLine("Higher Plane Intersection (LIN): {0}",B);
B = P + ( V * ( (SquaredMap.maxHeight-P.Z) / V.Z) );
Console.WriteLine("Higher Plane Intersection: {0}",B);
Vector2 a,b,min,max;
Vector2 start = Vector2.ComponentMin(A.Xy,B.Xy);
Vector2 finish = Vector2.ComponentMax(A.Xy,B.Xy);
Vector2 step = finish - start;
a = toTileBorderless(A.Xy);
b = toTileBorderless(B.Xy);
float steps = (step.X * step.Y) / 25.0f;
step /= steps;
min = Vector2.ComponentMax(Vector2.ComponentMin(a,b)-new Vector2(1,1),new Vector2());
max = Vector2.ComponentMin(Vector2.ComponentMax(a,b)+new Vector2(1,1),new Vector2(width,height));
int isteps = (int)steps;
Console.WriteLine("Checking Intersections: {0} -> {1}",min,max);
Vector2 pos = start,
tile = toTileBorderless(pos);
for (int nx = (int)min.X; nx < max.X; nx++){
for (int ny = (int)min.Y; ny < max.Y; ny++){
Vector3 isect = new Vector3();
//Console.WriteLine("Check Intersection: {0}/{1}",nx,ny);
Console.WriteLine("Interpolation: {0} - {1} - {2}",start,step,finish);
for (int n=0;n<4;n++){
try {
Model3D.Triangle t = model.triangles[tileIndex(nx,ny)];
if (Geometry.intersectTriangle(
P,
V,
t.VertexA,
t.VertexB,
t.VertexC,
out isect
)){
return isect;
for (int n=0;n<=isteps;){
Console.WriteLine("IP RUN[{0}]: {1} Tile: {2}",n,pos,tile);
if (new BooleanConditional()
.requires( tile.X >= 0)
.requires( tile.Y >= 0)
.requires( tile.X < width)
.requires( tile.Y < height)
.isSuccess()
){
Vector3 isect = new Vector3();
for (int nt=0;nt<4;nt++){
try {
Model3D.Triangle t = model.triangles[tileIndex((int)tile.X,(int)tile.Y)];
if (Geometry.intersectTriangle(
P,
V,
t.VertexA,
t.VertexB,
t.VertexC,
out isect
)){
return isect;
}
} catch (OutOfWorldException){
}
} catch (OutOfWorldException owe){
}
}
}
}
Vector2 nextTile = tile;
while (nextTile.Equals(tile)){
pos += step;
nextTile = toTileBorderless(pos);
n++;
}
tile = nextTile;
}
throw new OutOfWorldException();
}

View File

@ -20,15 +20,17 @@ namespace org.budnhead.core
return null;
}
public Vector3 Position{ get; set; } = new Vector3();
public Matrix4 Rotation { get; set; } = Matrix4.Identity;
public Matrix4 Scale { get; set; } = Matrix4.Identity;
public readonly BufferedValueInstance<Vector3> Position = new BufferedValueInstance<Vector3>(new Vector3());
public readonly BufferedValueInstance<Matrix4> Rotation = new BufferedValueInstance<Matrix4>(Matrix4.Identity);
public readonly BufferedValueInstance<Matrix4> Scale = new BufferedValueInstance<Matrix4>(Matrix4.Identity);
public Matrix4 Transformation {
get { return (Scale * Rotation) * Matrix4.CreateTranslation( Position ) ; }
get { return (Scale.Value * Rotation.Value) * Matrix4.CreateTranslation( Position.Value ) ; }
}
public Matrix4 BufferedTransformation {
get { return (Scale.BufferedValue * Rotation.BufferedValue) * Matrix4.CreateTranslation( Position.BufferedValue ) ; }
}
public void addChild(WorldObject wo){
if (!children.Contains(wo)){
children.Add(wo);
@ -44,7 +46,6 @@ namespace org.budnhead.core
public WorldObject[] Children{
get { return this.children.ToArray(); }
}
}
public class ObjectGroup : WorldObject {

View File

@ -34,7 +34,7 @@ namespace org.budnhead.graphics
buildMatrices();
}
public void setViewport(int width, int height)
override public void setViewport(int width, int height)
{
this.width = (float)width;
this.height = (float)height;
@ -54,7 +54,7 @@ namespace org.budnhead.graphics
aspect,
1.0f,
100000.0f
);
);
}
public Vector3 Position
@ -136,6 +136,21 @@ namespace org.budnhead.graphics
}
/**
* Group of Methods: LookXXXX
*
* Arrange Camera to point on/to/...
*
**/
public void lookAt(Vector3 position){
Vector3 v = position - Position;
v.Normalize();
View = v;
}
}

View File

@ -4,6 +4,7 @@ using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;
using OpenTK;
using org.budnhead.tools;
namespace org.budnhead.graphics
{
@ -33,13 +34,13 @@ namespace org.budnhead.graphics
public GLObject(int vertexes)
{
shaderProgram = GlobalDefaults.instance().DefaultShaderProgram;
shaderProgram = ResourceLibrary.getResource<ShaderProgram>("default");
init(vertexes);
prepareGL();
}
public GLObject(){
shaderProgram = GlobalDefaults.instance().DefaultShaderProgram;
shaderProgram = ResourceLibrary.getResource<ShaderProgram>("default");
init(0);
prepareGL();
}
@ -194,7 +195,7 @@ namespace org.budnhead.graphics
public void paint()
{
paint(GlobalDefaults.instance().ActiveScene);
paint(new GLCamera());
}
public void paint(GLSceneOrientation scene)

View File

@ -1,72 +0,0 @@
using System;
using OpenTK;
using org.budnhead.core;
namespace org.budnhead.graphics
{
public class GLScene
{
GLSceneOrientation sceneOrientation;
ShaderProgram shader;
WorldObject root;
public GLScene()
{
sceneOrientation = GlobalDefaults.instance().ActiveScene;
shader = GlobalDefaults.instance().DefaultShaderProgram;
root = new ObjectGroup();
}
public GLScene(GLSceneOrientation sceneOrientation)
{
this.sceneOrientation = sceneOrientation;
shader = GlobalDefaults.instance().DefaultShaderProgram;
root = new ObjectGroup();
}
public WorldObject RootObject {
get { return this.root; }
set { this.root = value; }
}
public void draw(){
Matrix4 objectMatrix = Matrix4.Identity;
shader.use();
if (root != null){
draw( objectMatrix, root );
}
foreach (WorldObject child in Actor.activeActors){
draw( objectMatrix, child );
}
}
public void draw(Matrix4 baseMatrix,WorldObject wo){
Matrix4 objectMatrix = wo.Transformation * baseMatrix;
//Console.WriteLine("draw(,{0}",wo);
//Console.WriteLine("draw(): o={0}\noM=\n{1}",wo,objectMatrix);
shader.setup(objectMatrix, sceneOrientation);
Model3D m3d = wo.getModel3D();
if (m3d != null){
m3d.draw();
}
foreach (WorldObject child in wo.Children){
draw( objectMatrix, child );
}
}
}
}

View File

@ -28,5 +28,16 @@ namespace org.budnhead.graphics
public Matrix4 mProjection(){
return this._mProjection;
}
public virtual void setViewport(int width, int height){
float aspect = width / height;
_mProjection = Matrix4.CreatePerspectiveFieldOfView(
MathHelper.PiOver2,
aspect,
1.0f,
100000.0f
);
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Threading;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
@ -8,13 +9,12 @@ using OpenTK;
using org.budnhead.core;
using org.budnhead.exceptions;
using org.budnhead.graphics;
using org.budnhead.graphics.primitives;
namespace bnhdemo
namespace org.budnhead.graphics
{
public class OpenGLWindow : GameWindow
public class GLWindow : GameWindow
{
private Point mouseCapturePosition;
private bool mouseCaptured;
@ -25,15 +25,11 @@ namespace bnhdemo
private Vector3 lookAt;
private float lookDistance;
private Cube cube,
c1, c2, c3;
private string titleMsg = "";
GLCamera sceneCamera;
GLScene scene;
Scene scene;
public OpenGLWindow()
public GLWindow()
:base(600, 600,
GraphicsMode.Default,
"nhEngine",
@ -44,37 +40,29 @@ namespace bnhdemo
{
VSync = VSyncMode.On;
sceneCamera = new GLCamera();
scene = new GLScene(sceneCamera);
scene = new Scene(sceneCamera);
}
public Scene Scene {
get { return this.scene; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
GL.ClearColor(0.05f, 0.05f, 0.05f, 0.0f);
GL.ClearColor(0.15f, 0.15f, 0.15f, 0.0f);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Normalize);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha,BlendingFactorDest.OneMinusSrcAlpha);
cube = new Cube(new Vector3(0,0,150), 16.0f);
c1 = new Cube(new Vector3(16,0,150), 8.0f);
c2 = new Cube(new Vector3(0,150,150), 8.0f);
c3 = new Cube(new Vector3(175,175,150), 8.0f);
lookAt = new Vector3(0,0,SquaredMap.maxHeight);
lookDistance = 2048;
arcUpDown = MathHelper.PiOver6;
arcLeftRight = MathHelper.PiOver4;
sceneCamera.setFoV(MathHelper.PiOver4);
sceneCamera.setFoV(MathHelper.PiOver2);
setupCamera();
scene.RootObject.addChild( cube );
scene.RootObject.addChild( c1 );
scene.RootObject.addChild( c2 );
scene.RootObject.addChild( c3 );
}
protected override void OnResize(EventArgs e)
@ -85,32 +73,6 @@ namespace bnhdemo
sceneCamera.setViewport(ClientRectangle.Width, ClientRectangle.Height);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
scene.draw();
SwapBuffers();
Title = string.Format("{0:F}/s {1:F}/s [{2:F}s] {3}", RenderFrequency,UpdateFrequency,UpdatePeriod,titleMsg);
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
Matrix4 m4 = Matrix4.CreateRotationZ(MathHelper.Pi / 90.0f);
cube.Rotation = m4 * cube.Rotation;
c1.Position = (m4.Inverted() * new Vector4(c1.Position)).Xyz;
c2.Rotation = (m4 * c2.Rotation);
c3.Position = (m4 * new Vector4(c3.Position)).Xyz;
Actor.updateAll( (float)UpdatePeriod );
}
private void captureMouse(){
mouseCapturePosition = new Point(Mouse.X, Mouse.Y);
mouseCaptured = true;
@ -141,7 +103,7 @@ namespace bnhdemo
{
switch (e.Button){
case OpenTK.Input.MouseButton.Left:
markMouse(e.X,e.Y);
//markMouse(e.X,e.Y);
break;
case OpenTK.Input.MouseButton.Right:
captureMouse();
@ -211,7 +173,7 @@ namespace bnhdemo
break;
case OpenTK.Input.Key.Space:
fireBallistic();
//fireBallistic();
break;
case OpenTK.Input.Key.Number1:
@ -234,7 +196,7 @@ namespace bnhdemo
}
}
/*
private void fireBallistic(){
Console.WriteLine("Fire Ballistic...");
BallisticActor ba = new BallisticActor(0);
@ -245,7 +207,7 @@ namespace bnhdemo
ba.Velocity.Normalize();
ba.Velocity *= 50;
}
*/
public void rotateUpDown(float arc)
{
@ -289,10 +251,20 @@ namespace bnhdemo
sceneCamera.Position = pos;
}
public GLScene Scene {
get { return this.scene; }
/* private void startTimers(){
timerGraphics.Change(0,50);
timerUpdates.Change(0,50);
}
private void stopTimers(){
timerGraphics.Change(Timeout.Infinite,Timeout.Infinite);
timerUpdates.Change(Timeout.Infinite,Timeout.Infinite);
}
*/
}
}

View File

@ -22,6 +22,10 @@ namespace org.budnhead.graphics
load(new StreamReader(filename),scale);
}
public LoadedModel(Stream stream){
load(new StreamReader(stream),1.0f);
}
private void load(TextReader reader){
load(reader,1);
}

View File

@ -9,7 +9,7 @@ namespace org.budnhead.graphics {
public class Model3D {
protected int vao,
protected int vao = 0,
vbo, // Vertex Buffer
cbo, // Color Buffer
cbo2, // Second Color Buffer
@ -24,15 +24,14 @@ namespace org.budnhead.graphics {
public Triangle[] triangles = new Triangle[0];
protected Model3D(){
vao = GL.GenVertexArray();
public Model3D(){
nTriangles = 0;
prepare();
}
protected void prepare(){
vao = GL.GenVertexArray();
vbo = GL.GenBuffer();
cbo = GL.GenBuffer();
cbo2 = GL.GenBuffer();
@ -110,6 +109,10 @@ namespace org.budnhead.graphics {
}
public void rebind(){
if (vao != 0){
prepare();
}
bindVertexes();
bindNormals();
bindColors();

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using org.budnhead.core;
using org.budnhead.tools;
namespace org.budnhead.graphics
{

View File

@ -0,0 +1,77 @@
using System;
using OpenTK;
using org.budnhead.core;
using org.budnhead.tools;
using System.Drawing;
namespace org.budnhead.graphics
{
public class Scene
{
ShaderProgram shader;
WorldObject root;
public Scene()
{
shader = ResourceLibrary.getResource<ShaderProgram>("default");
root = new ObjectGroup();
}
public Scene(GLSceneOrientation sceneOrientation)
{
shader = ResourceLibrary.getResource<ShaderProgram>("default");
root = new ObjectGroup();
}
public Scene(Scene source){
this.shader = source.shader;
this.root = source.root;
}
public WorldObject RootObject {
get { return this.root; }
set { this.root = value; }
}
public void draw(Viewport viewport){
Matrix4 objectMatrix = Matrix4.Identity;
shader.use();
if (root != null){
draw( viewport, objectMatrix, root );
}
foreach (WorldObject child in Actor.activeActors.ToArray()){
draw( viewport, objectMatrix, child );
}
}
public void draw(Viewport viewport,Matrix4 baseMatrix,WorldObject wo){
Matrix4 objectMatrix = wo.Transformation * baseMatrix;
//Console.WriteLine("draw(,{0}",wo);
//Console.WriteLine("draw(): o={0}\noM=\n{1}",wo,objectMatrix);
shader.setup(objectMatrix, viewport.SceneOrientation);
Model3D m3d = wo.getModel3D();
if (m3d != null){
m3d.draw();
}
foreach (WorldObject child in wo.Children){
draw( viewport, objectMatrix, child );
}
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using System.Threading;
using System.Collections.Generic;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using org.budnhead.core;
namespace org.budnhead.graphics
{
public class SceneWindow : GameWindow
{
Scene scene;
Viewport primaryViewport;
List<Viewport> viewports = new List<Viewport>();
internal SceneWindow()
:base(600, 600,
GraphicsMode.Default,
"nhEngine",
GameWindowFlags.Default,
DisplayDevice.Default,
3, 3,
GraphicsContextFlags.ForwardCompatible)
{
this.primaryViewport = new Viewport();
addViewport(primaryViewport);
lock(Engine.sceneWindows){
Engine.sceneWindows.Add(this);
}
}
public Viewport PrimaryViewport {
get { return this.primaryViewport; }
}
public Viewport[] Viewports {
get { return this.viewports.ToArray(); }
}
public override void Dispose()
{
lock (Engine.sceneWindows){
Engine.sceneWindows.Remove(this);
if (Engine.sceneWindows.Count == 0){
Engine.Shutdown();
}
}
base.Dispose();
}
public void addViewport(Viewport viewport){
if (viewport.Parent != null){
viewport.Parent.removeViewport(viewport);
}
this.viewports.Add(viewport);
viewport.Parent = this;
}
public void removeViewport(Viewport viewport){
if ((primaryViewport!=viewport) && (viewports.Contains(viewport))){
viewport.Parent = null;
viewports.Remove(viewport);
}
}
public Scene Scene {
get { return this.primaryViewport.Scene; }
set { lock(this){
this.primaryViewport.Scene = value;
} }
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
paint();
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Dispose();
}
public void paint(){
lock(this){
MakeCurrent();
paintViewports();
paintControls();
SwapBuffers();
}
}
public void paintViewports(){
Engine.ConsumerEnter();
foreach (Viewport viewport in this.viewports){
viewport.paint();
}
Engine.ConsumerExit();
}
public void paintControls(){
}
}
}

View File

@ -4,6 +4,8 @@ using System.IO;
using OpenTK.Graphics.OpenGL;
using OpenTK;
using org.budnhead.tools;
/**
* ShaderProgram Class
*
@ -70,8 +72,8 @@ namespace org.budnhead.graphics
public ShaderProgram(String vertexShader, String fragmentShader)
{
init(
new Shader(ShaderType.VertexShader, vertexShader),
new Shader(ShaderType.FragmentShader, fragmentShader)
ResourceLibrary.getResource<Shader>(vertexShader),
ResourceLibrary.getResource<Shader>(fragmentShader)
);
}

View File

@ -0,0 +1,67 @@
using System;
using System.Drawing;
using org.budnhead.core;
using org.budnhead.tools;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace org.budnhead.graphics
{
public class Viewport
{
GLSceneOrientation sceneOrientation;
Scene scene;
ShaderProgram shader;
public float Left { get; set; }
public float Top { get; set; }
public float Width { get; set; }
public float Height { get; set; }
public Viewport()
{
sceneOrientation = new GLSceneOrientation();
Left = 0.0f;
Top = 0.0f;
Width = 1.0f;
Height = 1.0f;
}
internal SceneWindow Parent { get; set; }
public Scene Scene {
get { return this.scene; }
set { this.scene = value; }
}
public GLSceneOrientation SceneOrientation {
get { return this.sceneOrientation; }
set { this.sceneOrientation = value; }
}
public void paint(){
Console.WriteLine("Viewport.paint()");
if (Parent != null){
Rectangle cr = Parent.ClientRectangle;
Rectangle vpr = new Rectangle(
(int)(cr.Left + (cr.Width * Left)),
(int)(cr.Top + (cr.Height * Top)),
(int)(cr.Width * Width),
(int)(cr.Height * Height)
);
Console.WriteLine(String.Format("Viewport: {0}",vpr));
GL.Viewport( vpr );
sceneOrientation.setViewport( cr.Width, cr.Height );
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Scene.draw(this);
}
}
}
}

View File

@ -9,8 +9,8 @@ namespace org.budnhead.graphics.primitives
{
public Cube(Vector3 position, float width)
{
Scale = Matrix4.CreateScale(width);
Position = position;
Scale.Value = Matrix4.CreateScale(width);
Position.Value = position;
}
public override Model3D getModel3D()

View File

@ -50,18 +50,15 @@
<Compile Include="graphics\GLObject.cs" />
<Compile Include="graphics\Shader.cs" />
<Compile Include="graphics\ShaderProgram.cs" />
<Compile Include="graphics\GlobalDefaults.cs" />
<Compile Include="graphics\primitives\Cube.cs" />
<Compile Include="graphics\primitives\Triangle.cs" />
<Compile Include="graphics\GLSceneOrientation.cs" />
<Compile Include="graphics\GLModel.cs" />
<Compile Include="graphics\GLScene.cs" />
<Compile Include="graphics\Scene.cs" />
<Compile Include="graphics\Model3D.cs" />
<Compile Include="graphics\ModelManager.cs" />
<Compile Include="FileHelper.cs" />
<Compile Include="graphics\Texture.cs" />
<Compile Include="graphics\LoadedModel.cs" />
<Compile Include="graphics\SquaredMap.cs" />
<Compile Include="exceptions\OutOfWorldException.cs" />
<Compile Include="audio\nhPlayer.cs" />
<Compile Include="audio\AudioDelegate.cs" />
@ -77,6 +74,25 @@
<Compile Include="core\Physics.cs" />
<Compile Include="core\WorldObject.cs" />
<Compile Include="exceptions\BudNHeadException.cs" />
<Compile Include="core\Engine.cs" />
<Compile Include="core\BufferedValue.cs" />
<Compile Include="graphics\GLWindow.cs" />
<Compile Include="core\SquaredMap.cs" />
<Compile Include="ui\Control.cs" />
<Compile Include="ui\Container.cs" />
<Compile Include="ui\events\UIEvent.cs" />
<Compile Include="ui\events\KeyPressedEvent.cs" />
<Compile Include="ui\ModifierKeys.cs" />
<Compile Include="core\ConsumerProducerLock.cs" />
<Compile Include="graphics\SceneWindow.cs" />
<Compile Include="tools\ResourceLibrary.cs" />
<Compile Include="tools\FileHelper.cs" />
<Compile Include="core\GlobalDefaults.cs" />
<Compile Include="tools\JobThreader.cs" />
<Compile Include="audio\streams\StreamSegment.cs" />
<Compile Include="audio\streams\AudioDomain.cs" />
<Compile Include="ui\SceneInScene.cs" />
<Compile Include="graphics\Viewport.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@ -159,6 +175,10 @@
</Folder>
<Folder Include="exceptions\" />
<Folder Include="core\" />
<Folder Include="ui\" />
<Folder Include="ui\events\" />
<Folder Include="tools\" />
<Folder Include="audio\streams\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\org.hwo.contracts\org.hwo.contracts.csproj">

View File

@ -1,7 +1,7 @@
using System;
using System.IO;
namespace org.budnhead.core
namespace org.budnhead.tools
{
public static class FileHelper
{

View File

@ -0,0 +1,84 @@
using System;
using System.Threading;
using System.Collections.Generic;
namespace org.budnhead.tools
{
public delegate T JobDelegate<T>();
public class JobThreader
{
Thread workerThread;
List<Job> queuedJobs;
public JobThreader()
{
workerThread = Thread.CurrentThread;
queuedJobs = new List<Job>();
}
public JobThreader(Thread workerThread){
this.workerThread = workerThread;
queuedJobs = new List<Job>();
}
public void execute(){
Monitor.Enter(queuedJobs);
foreach (Job j in queuedJobs){
j.execute();
}
queuedJobs.Clear();
Monitor.PulseAll(queuedJobs);
Monitor.Exit(queuedJobs);
}
public T execute<T>(JobDelegate<T> jobDelegate) where T : class{
if (workerThread.Equals(Thread.CurrentThread)){
return jobDelegate();
} else {
return Enqueue(jobDelegate);
}
}
private T Enqueue<T>(JobDelegate<T> jobDelegate) where T : class {
Job<T> job;
Monitor.Enter(queuedJobs);
job = new Job<T>(jobDelegate);
queuedJobs.Add(job);
Monitor.Wait(queuedJobs);
Monitor.Exit(queuedJobs);
return job.Result;
}
public abstract class Job{
public virtual void execute(){
}
}
public class Job<T> : Job{
T result;
JobDelegate<T> jobDelegate;
public Job(JobDelegate<T> jobDelegate){
this.jobDelegate = jobDelegate;
}
public override void execute()
{
this.result = this.jobDelegate();
}
public T Result {
get { return this.result; }
}
}
}
}

View File

@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.IO;
using org.hwo.contracts;
namespace org.budnhead.tools
{
public static class ResourceLibrary
{
static Dictionary<Type,Dictionary<string,object>>
resourceTypes = new Dictionary<Type, Dictionary<string, object>>();
static List<string>
resourcePaths = new List<string>(new string[]{"."});
static Dictionary<Type,string> prefixes = new Dictionary<Type, string>();
static Dictionary<Type,string> suffixes = new Dictionary<Type, string>();
internal static bool initializeResourceType(Type t,string prefix,string suffix,bool initializeBases){
ConstructorInfo ci = null;
new BooleanConditional()
.requiresValid(ref ci,delegate { return t.GetConstructor(new Type[]{ typeof(Stream) }); })
.does( delegate { initializeResourceType(t,prefix,suffix); } );
if (initializeBases && (t.BaseType != null)){
initializeResourceType(t.BaseType,prefix,suffix,true);
}
return true;
}
internal static bool initializeResourceType(Type t,string prefix,string suffix){
if (prefix != null)
prefixes.Add(t,prefix);
if (suffix != null)
suffixes.Add(t,suffix);
return true;
}
static T findLoadedInstance<T>(string name){
if (resourceTypes.ContainsKey(typeof(T))){
if (resourceTypes[typeof(T)].ContainsKey(name)){
return (T)resourceTypes[typeof(T)][name];
}
}
throw new KeyNotFoundException("");
}
public static void cacheInstance<T>(string name,T instance){
if (!resourceTypes.ContainsKey(typeof(T))){
resourceTypes.Add(typeof(T),new Dictionary<string, object>());
}
resourceTypes[typeof(T)].Add(name,instance);
}
public static T getResource<T>(string name){
try {
return findLoadedInstance<T>(name);
} catch (KeyNotFoundException){
string p="",s="";
if (prefixes.ContainsKey(typeof(T))){
p = prefixes[typeof(T)];
}
if (suffixes.ContainsKey(typeof(T))){
s = suffixes[typeof(T)];
}
string resFileName = FileHelper.findFile(String.Format("{0}{1}{2}",p,name,s),resourcePaths.ToArray());
if (resFileName != null){
Stream resStream = new FileStream(resFileName,FileMode.Open);
ConstructorInfo ci = typeof(T).GetConstructor(new Type[]{ typeof(Stream) });
T o = (T)ci.Invoke(new object[]{ resStream });
cacheInstance(name,o);
return o;
}
throw new KeyNotFoundException(String.Format("ResourceLibrary[{0}:{1}]",typeof(T).ToString(),name));
}
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
namespace org.budnhead
{
public class Container : Control
{
private List<Control> children;
public Container()
{
this.children = new List<Control>();
}
public void addChild(Control control){
if (control.parent != null){
control.parent.removeChild(control);
}
this.children.Add(control);
}
public void removeChild(Control control){
this.children.Remove(control);
}
public Control[] Children {
get { return this.children.ToArray(); }
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using OpenTK;
namespace org.budnhead
{
public class Control
{
internal Container parent;
public Control()
{
}
public Vector2 Position { get; set; }
public Vector2 Size { get; set; }
public Container Parent {
get { return this.parent; }
set { if (value == null) { if (this.parent != null) this.parent.removeChild(this); } else { value.addChild(this); } }
}
public virtual void paint(){
paintBorder();
paintControl();
}
public virtual void paintBorder(){
}
public virtual void paintControl(){
}
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace org.budnhead
{
public enum ModifierKeys
{
NONE,SHIFT,CONTROL,COMMAND,WIN,CONTEXT
}
}

View File

@ -0,0 +1,27 @@
using System;
using org.budnhead.graphics;
using OpenTK.Graphics.OpenGL;
namespace org.budnhead
{
public class SceneInScene : Control
{
Scene scene;
public SceneInScene()
{
}
public override void paintControl()
{
if (scene != null){
// ToDo: Prepare Transformation Matrix and Clipping
// ... scene.draw();
}
}
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace org.budnhead
{
public class KeyPressedEvent : UIEvent
{
public KeyPressedEvent(char keyChar,ModifierKeys modifierKeys)
{
KeyChar = keyChar;
Modifier = modifierKeys;
}
public char KeyChar { get; private set; }
public ModifierKeys Modifier { get; private set; }
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace org.budnhead
{
public class UIEvent
{
public UIEvent()
{
}
}
}

View File

@ -41,13 +41,21 @@ namespace org.hwo.contracts
return this;
}
public Conditional<T> assigns<AT>(ref AT target,assignDelegate<AT> assigner){
public Conditional<T> assigns<AT>(ref AT target,assignDelegate<AT> assigner) {
if (success){
target = assigner();
}
return this;
}
public Conditional<T> requiresValid<AT>(ref AT target,assignDelegate<AT> assigner){
if (success){
target = assigner();
success = target != null;
}
return this;
}
public bool isSuccess(){
return this.success;
}