/// <summary> /// Este es el método importante de esta clase, ya que este menú es netamente informativo de /// que está haciendo el usuario en este momento. /// </summary> /// <param name="scene"></param> protected void DrawMenuInfo(Scene.Scene scene) { // Mostramos que hubo un error IntPtr font = Glut.GLUT_BITMAP_HELVETICA_12; Gl.glColor3d(0, 0, 0); Gl.glRasterPos2d(OffsetX + 20, OffsetY + HEIGHT / 2 + 4); string text = ""; if (scene.sceneState == SceneState.Edit) text = "Editando " + scene.SelectedButton.CurrentProperty + ": " + scene.InputString; if (scene.sceneState == SceneState.LoadObj) { text = "Escribir nombre archivo (sin extensión)" + ": " + scene.InputString; } else if (scene.sceneState == SceneState.Error) text = "No se pudo parsear el input. Presione cualquier tecla para continuar."; else if (scene.sceneState == SceneState.Create) { text = "Crear "; if (scene.FigureToCreate == Figures.FigureEnum.Triangle) text += " triángulo"; else if (scene.FigureToCreate == Figures.FigureEnum.Sphere) text += " esfera"; } else if (scene.sceneState == SceneState.Save) text = "Escena fue guardada con éxito."; else if (scene.sceneState == SceneState.Free) text = "Comandos: 'L' para cargar modelos, 'C + T + ENTER' para crear triángulo, 'C + S + ENTER' para crear esfera, 'SUPR' para borrar objeto seleccionado, 'SPACE' para guardar"; Glut.glutBitmapString(font, text); }
protected static void LoadObj(Scene.Scene scene, byte key) { if (key == ENTER) { scene.LoadObjModel(scene.InputString); scene.sceneState = SceneState.Free; } else if (key == ESCAPE) { scene.SelectedButton.COMPLETED = false; scene.SelectedButton.RestartInput(); scene.sceneState = SceneState.Free; } else { string input = scene.InputString; if (key == BACKSPACE) { if (input.Length > 0) { input = input.Substring(0, input.Length - 1); } } else { input += ((char)key).ToString(); } scene.InputString = input; } }
static void Main(string[] args) { scene = new Scene.Scene(800, 600); menuList.Add(new InfoMenu(300, scene.HEIGHT - 20, 0, bottomHeight + 20)); menuList.Add(new BottomMenu(scene.WIDTH, bottomHeight, 0, 0)); Glut.glutInit(); Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_RGBA | Glut.GLUT_DEPTH); Glut.glutInitWindowSize(scene.WIDTH + menuList[0].WIDTH, scene.HEIGHT + menuList[1].HEIGHT); Glut.glutInitWindowPosition(100, 10); int id = Glut.glutCreateWindow("Scene Editor"); Init(); Glut.glutDisplayFunc(new Glut.DisplayCallback(Draw)); Glut.glutKeyboardFunc(new Glut.KeyboardCallback(KeyboardHandle)); Glut.glutMouseFunc(new Glut.MouseCallback(MouseHandle)); Glut.glutMouseWheelFunc(new Glut.MouseWheelCallback(MouseWheelHandle)); //Glut.glutReshapeFunc(new Glut.ReshapeCallback(Resize)); Glut.glutTimerFunc(1000 / 60, Update, 0); Glut.glutMainLoop(); }
protected static void CreateInput(Scene.Scene scene, byte key) { if (key == 't') { scene.FigureToCreate = FigureEnum.Triangle; } else if (key == 's') { scene.FigureToCreate = FigureEnum.Sphere; } else if (key == ENTER) { if (scene.FigureToCreate == FigureEnum.Triangle) { Triangle triangle = new Triangle(); scene.AddFigure(triangle); scene.SelectFigure(triangle); scene.sceneState = SceneState.Free; scene.FigureToCreate = FigureEnum.None; } else if (scene.FigureToCreate == FigureEnum.Sphere) { Sphere sphere = new Sphere(); scene.AddFigure(sphere); scene.SelectFigure(sphere); scene.sceneState = SceneState.Free; scene.FigureToCreate = FigureEnum.None; } } if (key == ESCAPE) { scene.FigureToCreate = FigureEnum.None; scene.sceneState = SceneState.Free; } }
public override void Draw(Scene.Scene scene) { // Dibujamos el fondo del menú DrawMenuBox(); if (scene.SelectedFigure != null) scene.SelectedFigure.Print(scene, 5 * Margin, 20 * Margin); }
public override void MouseInput(Scene.Scene scene, int button, int state, int x, int y) { // Obtenemos la figura seleccionada y vemos si apretamos alguno de los botones if(scene.SelectedFigure != null) { scene.SelectedFigure.MouseMenuInput(scene, button, state, x, y); } }
static public void Run(Scene.Scene scene, bool select, List <BaseMenu> menuList) { Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); Gl.glClearColor(0, 0, 0, 1); //TODO: Handle this from XML DrawScene(scene, select, leftMenu: menuList[0]); DrawMenu(scene, select, menuList); if (!select) { Glut.glutSwapBuffers(); } }
protected static void ClickScene(Scene.Scene scene, List<BaseMenu> menuList, int x, int y) { /** * Vamos a ver que objeto se seleccionó. Hay varias formas de hacer esto. Un approach más matemático * (e inclusive más intuitivo, pero no por eso el más simple) es proyectar el mouse como un rayo y ver * que objeto choca con ese rayo (al más puro estilo de un ray tracer). * * No obstante, una solución mucho más fácil (kudos Joaquín Jaramillo por mencionarlo) es renderiar * cada objeto con un color único (provisto por la escena) el cual cual funciona como ID. * Luego simplemente necesitamos ver el color del pixel para saber que objeto ha sido seleccionado. * Hay que tener cuidado de no asignar como ID el color del fondo, * con tal de poder detectar que no se ha seleccionado ningún objeto. **/ // Deshabilitamos cualquier efecto que haría que un objeto no tuviese un color uniforme Gl.glDisable(Gl.GL_LIGHTING); Gl.glDisable(Gl.GL_TEXTURE_2D); Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); // Dibujamos la escena con el modo especial DrawClass.Run(scene, true, menuList); // Pixel para obtener el color byte[] pixel = new byte[3]; // Leemos el color del pixel en cuestión // La coordenada Y es (WIDTH - yMouse) debido a una disparidad de cual es el (0,0) de la ventana // entre OpenGL (esquina inferior izquierda) y Windows (esquina superior izquierda). // TODO: Generalizar offsets Gl.glReadPixels(x, scene.HEIGHT + menuList[1].HEIGHT - y, 1, 1, Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, pixel); // Ahora, si tenemos un color no fondo (negro 0,0,0), buscamos el objeto en cuestión if (pixel[0] != 0 || pixel[1] != 0 || pixel[2] != 0) { Figure selectedFigure = scene.FindFigure(pixel); if (selectedFigure != null) { scene.SelectFigure(selectedFigure); } } // Independiente de lo ocurrido, reestablecemos los modos Gl.glEnable(Gl.GL_LIGHTING); Gl.glEnable(Gl.GL_TEXTURE_2D); }
private static void DrawMenu(Scene.Scene scene, bool select, List <BaseMenu> menuList) { Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); Gl.glDisable(Gl.GL_DEPTH_TEST); Gl.glDisable(Gl.GL_LIGHTING); Gl.glDisable(Gl.GL_CULL_FACE); foreach (BaseMenu menu in menuList) { menu.Draw(scene); } Gl.glEnable(Gl.GL_DEPTH_TEST); Gl.glEnable(Gl.GL_LIGHTING); Gl.glEnable(Gl.GL_CULL_FACE); }
private static void DrawScene(Scene.Scene scene, bool select, BaseMenu leftMenu) { Program.Resize(scene.WIDTH, scene.HEIGHT); Camera camera = scene.SceneCamera; List <Figure> objects = scene.SceneFigures; List <Light> lights = scene.SceneLights; Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); Glu.gluLookAt(camera.Position.x, camera.Position.y, camera.Position.z, camera.Target.x, camera.Target.y, camera.Target.z, camera.Up.x, camera.Up.y, camera.Up.z); foreach (Figure figure in objects) { figure.Draw(select); } SetLighting(lights); }
/// <summary> /// Punto de entrada de un click del mouse /// </summary> /// <param name="button">Que botón fue usado</param> /// <param name="state">Cual es el estado de este botón (que evento fue gatillado)</param> /// <param name="x">Coordenada X del mouse</param> /// <param name="y">Coordenada Y del mouse</param> /// <param name="scene">La escena</param> /// <param name="menuList">Los menus</param> public static void MouseInput(int button, int state, int x, int y, Scene.Scene scene, List<BaseMenu> menuList) { // Vemos que tipo de evento obtenemos // Si apretamos el botón izquierdo if (button == Glut.GLUT_LEFT_BUTTON) { // Si lo apretamos (no release) if (state == Glut.GLUT_DOWN) { // Tenemos que ver donde cayó el click if (x > menuList[0].WIDTH) { // El click fue en la escena ClickScene(scene, menuList, x, y); } else // El click fue en el menú { foreach (BaseMenu menu in menuList) menu.MouseInput(scene, button, state, x, y); } } } }
/// <summary> /// Método que maneja el input del menu /// </summary> /// <param name='scene'>La clase que representa la escena</param> public override void KeyboardInput(Scene.Scene scene, byte key, int x, int y) { }
protected static void ErrorInput(Scene.Scene scene, byte key) { scene.sceneState = SceneState.Edit; scene.InputString = ""; }
static public void KeyboardInput(byte key, int x, int y, Scene.Scene scene, List <BaseMenu> menuList) { Camera camera = scene.SceneCamera; List <Figure> objectList = scene.SceneFigures; List <Light> lightList = scene.SceneLights; if (scene.sceneState == SceneState.Save) { scene.sceneState = SceneState.Free; } else if (scene.sceneState == SceneState.Free) { if (key == SPACE) { scene.Save("output.xml"); scene.sceneState = SceneState.Save; } if (key == DELETE) { scene.DeleteSelectedFigure(); } if (key == 'l') { scene.InputString = ""; scene.sceneState = SceneState.LoadObj; } if (key == 'c') { scene.sceneState = SceneState.Create; } if (key == '1') { camera.cameraMode = CameraMode.Z; } if (key == '2') { camera.cameraMode = CameraMode.X; } if (key == '3') { camera.cameraMode = CameraMode.Y; } scene.SceneCamera.HandleInput(key); foreach (BaseMenu menu in menuList) { menu.KeyboardInput(scene, key, x, y); } } else if (scene.sceneState == SceneState.Edit) { EditInput(scene, key); } else if (scene.sceneState == SceneState.Error) { ErrorInput(scene, key); } else if (scene.sceneState == SceneState.Create) { CreateInput(scene, key); } else if (scene.sceneState == SceneState.LoadObj) { LoadObj(scene, key); } }
public override void MouseInput(Scene.Scene scene, int button, int state, int x, int y) { //throw new NotImplementedException(); }
public override void KeyboardInput(Scene.Scene scene, byte key, int x, int y) { //throw new NotImplementedException(); }
public override void Draw(Scene.Scene scene) { DrawMenuBox(); DrawMenuInfo(scene); }
static void Main(string[] args) { // Creamos la escena scene = new Scene.Scene(800, 600); // Creamos los menues // ES IMPORTANTE QUE <InfoMenu> VAYA PRIMERO int bottomHeight = 50; menuList.Add(new InfoMenu(300, scene.HEIGHT - 20, 0, bottomHeight + 20)); // TODO: Generalizar los offsets menuList.Add(new BottomMenu(scene.WIDTH+menuList[0].WIDTH, bottomHeight, 0, 0)); // Inicializamos GLUT Glut.glutInit(); // Inicializamos un display, y le indicamos con OR los distintos flags Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_RGBA | Glut.GLUT_DEPTH); // Hacemos la ventana algo más grande que el viewport de escena para tener // como mostrar información extra Glut.glutInitWindowSize(scene.WIDTH + menuList[0].WIDTH, scene.HEIGHT + menuList[1].HEIGHT); Glut.glutInitWindowPosition(100, 10); // Creamos el display int id = Glut.glutCreateWindow("Scene Editor"); // Inicializamos el programa Init(); /** * Linkeamos a GLUT los handlers que creamos para los eventos. * * OJO: Solo tenemos permiso a dibujar en la llamada que definimos para DisplayFunc **/ Glut.glutDisplayFunc(new Glut.DisplayCallback(Draw)); // Dibujar Glut.glutKeyboardFunc(new Glut.KeyboardCallback(KeyboardHandle)); // Input Teclado Glut.glutMouseFunc(new Glut.MouseCallback(MouseHandle)); // Input Mouse Glut.glutMouseWheelFunc(new Glut.MouseWheelCallback(MouseWheelHandle)); // Rueda del mouse //Glut.glutReshapeFunc(new Glut.ReshapeCallback(Resize)); // Resize de la ventana // glutTimerFunc llama a la función entregada en el tiempo indicado en ms, y le entrega a // tal función el value, para poner identificar en caso de ser necesario. // Ojo que no se pueden cancelar callbacks. En tal caso hay que ignorarlos vía estados. // 34 ms = ~30 FPS Glut.glutTimerFunc(34, Update, 0); // Iniciamos el Loop gráfico Glut.glutMainLoop(); }
protected static void EditInput(Scene.Scene scene, byte key) { if (key == ENTER) { if (scene.SelectedButton.ParseInput(scene.InputString)) { scene.InputString = ""; if (scene.SelectedButton.COMPLETED) { scene.SelectedButton.COMPLETED = false; scene.SelectedButton.selected = false; scene.sceneState = SceneState.Free; } else { } } else { scene.sceneState = SceneState.Error; } } else if (key == TAB) { scene.SelectedButton.ParseInput(Scene.Scene.UNDEFINED.ToString()); if (scene.SelectedButton.COMPLETED) { scene.SelectedButton.COMPLETED = false; scene.SelectedButton.selected = false; scene.sceneState = SceneState.Free; } } else if (key == ESCAPE) { scene.SelectedButton.COMPLETED = false; scene.SelectedButton.selected = false; scene.SelectedButton.RestartInput(); scene.sceneState = SceneState.Free; } else { if (scene.SelectedFigure is Model && scene.SelectedButton != null && (key == 'a' || key == 's' || key == 'd' || key == 'w' || key == 'i' || key == 'k')) { Model m = (Model)scene.SelectedFigure; if (key == 'a') { m.EditPropertyByOffset(scene.SelectedButton.Name, new Vector(-0.1, 0, 0)); } else if (key == 'd') { m.EditPropertyByOffset(scene.SelectedButton.Name, new Vector(0.1, 0, 0)); } else if (key == 'w') { m.EditPropertyByOffset(scene.SelectedButton.Name, new Vector(0, 0.1, 0)); } else if (key == 's') { m.EditPropertyByOffset(scene.SelectedButton.Name, new Vector(0, -0.1, 0)); } else if (key == 'k') { m.EditPropertyByOffset(scene.SelectedButton.Name, new Vector(0, 0, -0.1)); } else if (key == 'i') { m.EditPropertyByOffset(scene.SelectedButton.Name, new Vector(0, 0, 0.1)); } } else { string input = scene.InputString; if (key == BACKSPACE) { if (input.Length > 0) { input = input.Substring(0, input.Length - 1); } } else { input += ((char)key).ToString(); } scene.InputString = input; } } }
public static void MouseWheelHandle(Scene.Scene scene, List<BaseMenu> menuList, int wheel, int dir, int x, int y) { // Por ahora hacemos el zoom scene.SceneCamera.HandleMouseWheel(wheel, dir, x, y); }
public override void MouseInput(Scene.Scene scene, int button, int state, int x, int y) { // Vemos si el click fue dentro del botón if(x > X && x < (X + WIDTH)) { if(y > Y && y < (Y+HEIGHT)) { // Si no estamos editando una propiedad, marcamos que la estamos editando if(scene.sceneState == SceneState.Free) { if (scene.SelectedButton != null) scene.SelectedButton.selected = false; scene.sceneState = SceneState.Edit; // Decimos que este es el botón siendo seleccionado scene.SelectedButton = this; selected = true; // Borramos el input scene.InputString = ""; // Reiniciamos el input currentInput = UndefinedInputVector(); } } } }
/// <summary> /// Dibuja el botón. /// </summary> /// <param name="text">Texto a desplegar dentro del botón</param> public override void Draw(Scene.Scene scene) { IntPtr middleFont = Glut.GLUT_BITMAP_HELVETICA_12; Gl.glBegin(Gl.GL_QUADS); //Dibujamos el margen Gl.glColor3fv(MathUtils.GetVector3Array(outerColor)); Gl.glVertex2d(X, Y); Gl.glVertex2d(X + WIDTH, Y); Gl.glVertex2d(X + WIDTH, Y + HEIGHT); Gl.glVertex2d(X, Y + HEIGHT); // El rectángulo que tiene la información if (!selected) Gl.glColor3fv(MathUtils.GetVector3Array(innerColor)); else Gl.glColor3fv(MathUtils.GetVector3Array(selectedColor)); Gl.glVertex2d(X + Margin, Y + Margin); Gl.glVertex2d(X + WIDTH - Margin, Y + Margin); Gl.glVertex2d(X + WIDTH - Margin, Y + HEIGHT - Margin); Gl.glVertex2d(X + Margin, Y + HEIGHT - Margin); Gl.glEnd(); Gl.glColor3d(0, 0, 0); Figure.WriteText(middleFont, Name, X+5, Y+HEIGHT/2+5); }