Example #1
0
File: m_gif.c Project: ifzz/juno
static int l_gif_gc(lua_State *L) {
  Gif *self = luaL_checkudata(L, 1, CLASS_NAME);
  free(self->buf);
  /* Not closed? close now */
  if (self->state == STATE_ACTIVE) {
    jo_gif_end(&self->gif);
  }
  return 0;
}
Example #2
0
File: m_gif.c Project: ifzz/juno
static int l_gif_close(lua_State *L) {
  Gif *self = luaL_checkudata(L, 1, CLASS_NAME);
  if (self->state == STATE_CLOSED) {
    luaL_error(L, "state already closed");
  }
  self->state = STATE_CLOSED;
  jo_gif_end(&self->gif);
  return 0;
}
Example #3
0
void gui_tick(VideoMode mode, r32 gui_time, r32 gui_dt)
{
    persist bool flag_DrawDroneGoto     = true;
    persist bool flag_DrawDrone         = true;
    persist bool flag_DrawVisibleRegion = true;
    persist bool flag_DrawTargets       = true;
    persist bool flag_DrawObstacles     = true;
    persist bool flag_Paused            = false;
    persist bool flag_Recording         = false;
    persist bool flag_SetupRecord       = false;

    persist int record_from = 0;
    persist int record_to = 0;
    persist int record_frame_skip = 1;
    persist int record_width = 0;
    persist int record_height = 0;
    persist float record_region_x = -1.0f;
    persist float record_region_y = -1.0f;
    persist float record_region_scale = 2.0f;
    persist jo_gif_t record_gif;

    persist int seek_cursor = 0;
    persist int selected_target = -1;

    persist Color color_Clear          = { 0.00f, 0.00f, 0.00f, 1.00f };
    persist Color color_Tiles          = { 0.20f, 0.35f, 0.46f, 0.66f };
    persist Color color_Grid           = { 0.00f, 0.00f, 0.00f, 1.00f };
    persist Color color_VisibleRegion  = { 0.87f, 0.93f, 0.84f, 0.50f };
    persist Color color_GreenLine      = { 0.10f, 1.00f, 0.20f, 1.00f };
    persist Color color_SelectedTarget = { 0.85f, 0.34f, 0.32f, 1.00f };
    persist Color color_Targets        = { 0.85f, 0.83f, 0.37f, 1.00f };
    persist Color color_Obstacles      = { 0.43f, 0.76f, 0.79f, 1.00f };
    persist Color color_Drone          = { 0.87f, 0.93f, 0.84f, 0.50f };
    persist Color color_DroneGoto      = { 0.87f, 0.93f, 0.84f, 0.50f };
    #define RGBA(C) C.r, C.g, C.b, C.a

    persist float send_timer = 0.0f;
    persist float send_interval = 1.0f; // In simulation time units

    NDC_SCALE_X = (mode.height / (r32)mode.width) / 12.0f;
    NDC_SCALE_Y = 1.0f / 12.0f;

    if (flag_Recording || flag_SetupRecord)
    {
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        float Ax = 2.0f / record_region_scale;
        float Bx = -1.0f - Ax*record_region_x;
        float Ay = 2.0f / record_region_scale;
        float By = -1.0f - Ay*record_region_y;
        float modelview[] = {
            Ax,   0.0f, 0.0f, 0.0f,
            0.0f, Ay,   0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, 0.0f,
            Bx,   By,   0.0f, 1.0f
        };
        glLoadMatrixf(modelview);
    }
    else
    {
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

    if (!flag_Paused)
    {
        if (flag_Recording)
        {
            if (seek_cursor >= record_to)
            {
                flag_Paused = true;
                flag_Recording = false;
                seek_cursor = record_from;
                jo_gif_end(&record_gif);
            }
            else if (seek_cursor + record_frame_skip >= record_to)
            {
                // clamp to end
                seek_cursor = record_to;
            }
            else
            {
                seek_cursor += record_frame_skip;
            }
        }
        else if (seek_cursor < HISTORY_LENGTH-1)
        {
            seek_cursor++;
        }
        else
        {
            sim_Command cmd;

            if (!sim_recv_cmd(&cmd))
            {
                cmd.type = sim_CommandType_NoCommand;
                cmd.x = 0.0f;
                cmd.y = 0.0f;
                cmd.i = 0;
            }

            STATE = sim_tick(STATE, cmd);
            add_history(cmd, STATE);
            seek_cursor = HISTORY_LENGTH-1;

            send_timer -= Sim_Timestep;
            if (send_timer <= 0.0f)
            {
                sim_send_state(&STATE);
                send_timer += send_interval;
            }
        }
    }

    sim_State draw_state = HISTORY_STATE[seek_cursor];
    sim_Drone drone = draw_state.drone;
    sim_Robot *robots = draw_state.robots;
    sim_Robot *targets = draw_state.robots;
    sim_Robot *obstacles = draw_state.robots + Num_Targets;

    if (flag_Recording || flag_SetupRecord)
    {
        glViewport(0, 0, record_width, record_height);
    }
    else
    {
        glViewport(0, 0, mode.width, mode.height);
    }

    glClearColor(RGBA(color_Clear));
    glClear(GL_COLOR_BUFFER_BIT);
    glLineWidth(2.0f);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // draw grid tiles
    glBegin(GL_TRIANGLES);
    {
        color4f(color_Tiles);
        for (int yi = 0; yi < 20; yi++)
        for (int xi = 0; xi < 20; xi++)
        {
            r32 x = xi*1.0f;
            r32 y = yi*1.0f;
            fill_square(x, y, x+1.0f, y+1.0f);
        }
    }
    glEnd();

    glBegin(GL_LINES);
    {
        // draw grid lines
        color4f(color_Grid);
        for (int i = 0; i <= 20; i++)
        {
            r32 x = (r32)i;
            draw_line(x, 0.0f, x, 20.0f);
            draw_line(0.0f, x, 20.0f, x);
        }

        // draw visible region
        if (flag_DrawVisibleRegion)
        {
            color4f(color_VisibleRegion);
            draw_circle(drone.x, drone.y, 2.5f);
        }

        // draw green line
        color4f(color_GreenLine);
        draw_line(0.0f, 20.0f, 20.0f, 20.0f);

        // draw targets
        if (flag_DrawTargets)
        {
            color4f(color_Targets);
            for (int i = 0; i < Num_Targets; i++)
                draw_robot(targets[i]);
            if (selected_target >= 0)
            {
                color4f(color_SelectedTarget);
                draw_robot(targets[selected_target]);
            }
        }

        // draw obstacles
        if (flag_DrawObstacles)
        {
            color4f(color_Obstacles);
            for (int i = 0; i < Num_Obstacles; i++)
                draw_robot(obstacles[i]);
        }

        // draw drone
        if (flag_DrawDrone)
        {
            color4f(color_Drone);
            draw_line(drone.x - 0.5f, drone.y,
                      drone.x + 0.5f, drone.y);
            draw_line(drone.x, drone.y - 0.5f,
                      drone.x, drone.y + 0.5f);
        }

        // draw drone goto
        if (flag_DrawDroneGoto)
        {
            color4f(color_DroneGoto);
            draw_circle(drone.xr, drone.yr, 0.45f);
        }

        // draw indicators of magnet or bumper activations
        for (int i = 0; i < Num_Targets; i++)
        {
            r32 x = targets[i].x;
            r32 y = targets[i].y;
            if (targets[i].action.was_bumped)
            {
                glColor4f(1.0f, 0.3f, 0.1f, 1.0f);
                draw_circle(x, y, 0.5f);
            }
            else if (targets[i].action.was_top_touched)
            {
                glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
                draw_circle(x, y, 0.5f);
            }
        }
    }
    glEnd();

    // TODO: Change capture res?
    if (flag_Recording)
    {
        static unsigned char capture_data[1024*1024*4];
        Assert(sizeof(capture_data) >=
               record_width*record_height*4);
        glReadPixels(0, 0,
                     record_width,
                     record_height,
                     GL_RGBA,
                     GL_UNSIGNED_BYTE,
                     capture_data);

        jo_gif_frame(&record_gif, capture_data,
                     2, false);
    }

    ImGui_ImplSdl_NewFrame(mode.window);

    // DRAW FLAGS
    if (ImGui::CollapsingHeader("Rendering"))
    {
        ImGui::Checkbox("Drone goto", &flag_DrawDroneGoto);
        ImGui::Checkbox("Drone", &flag_DrawDrone);
        ImGui::Checkbox("Visible region", &flag_DrawVisibleRegion);
        ImGui::Checkbox("Targets", &flag_DrawTargets);
        ImGui::Checkbox("Obstacles", &flag_DrawObstacles);
    } // END DRAW FLAGS

    // COLORS
    if (ImGui::CollapsingHeader("Colors"))
    {
        ImGui::ColorEdit4("Clear", &color_Clear.r);
        ImGui::ColorEdit4("Grid", &color_Grid.r);
        ImGui::ColorEdit4("VisibleRegion", &color_VisibleRegion.r);
        ImGui::ColorEdit4("GreenLine", &color_GreenLine.r);
        ImGui::ColorEdit4("Targets", &color_Targets.r);
        ImGui::ColorEdit4("Obstacles", &color_Obstacles.r);
        ImGui::ColorEdit4("Drone", &color_Drone.r);
        ImGui::ColorEdit4("DroneGoto", &color_DroneGoto.r);
    } // END COLORS

    // REWIND HISTORY
    if (ImGui::CollapsingHeader("Seek##header"))
    {
        ImGui::Checkbox("Paused", &flag_Paused);
        ImGui::SliderInt("Seek##bar", &seek_cursor, 0, HISTORY_LENGTH-1);
        ImGui::InputInt("Seek frame", &seek_cursor);
        if (seek_cursor < 0) seek_cursor = 0;
        if (seek_cursor > HISTORY_LENGTH-1) seek_cursor = HISTORY_LENGTH-1;
        ImGui::Text("Time: %.2f seconds", (seek_cursor+1) * Sim_Timestep);
    } // END REWIND HISTORY

    // ROBOTS
    if (ImGui::CollapsingHeader("Robots"))
    {
        ImGui::Columns(4, "RobotsColumns");
        ImGui::Separator();
        ImGui::Text("ID"); ImGui::NextColumn();
        ImGui::Text("X"); ImGui::NextColumn();
        ImGui::Text("Y"); ImGui::NextColumn();
        ImGui::Text("Angle"); ImGui::NextColumn();
        ImGui::Separator();
        for (int i = 0; i < Num_Targets; i++)
        {
            char label[32];
            sprintf(label, "%02d", i);
            if (ImGui::Selectable(label, selected_target == i, ImGuiSelectableFlags_SpanAllColumns))
                selected_target = i;
            ImGui::NextColumn();
            ImGui::Text("%.2f", robots[i].x); ImGui::NextColumn();
            ImGui::Text("%.2f", robots[i].y); ImGui::NextColumn();
            ImGui::Text("%.2f", robots[i].q); ImGui::NextColumn();
        }
        ImGui::Columns(1);
        ImGui::Separator();
    }
    else
    {
        selected_target = -1;
    } // END ROBOTS

    // COMMUNICATION
    if (ImGui::CollapsingHeader("Communication"))
    {
        ImGui::TextWrapped("The rate at which the state is "
                           "sent can be changed using this slider. "
                           "The slider value represents the time "
                           "interval (in simulation time) "
                           "between each send.");
        ImGui::SliderFloat("Send interval", &send_interval,
                           Sim_Timestep, 1.0f);
        ImGui::Separator();

        ImGui::Text("Last 10 non-trivial commands received:");
        ImGui::Columns(5, "CommunicationColumns");
        ImGui::Separator();
        ImGui::Text("Time"); ImGui::NextColumn();
        ImGui::Text("type"); ImGui::NextColumn();
        ImGui::Text("x"); ImGui::NextColumn();
        ImGui::Text("y"); ImGui::NextColumn();
        ImGui::Text("i"); ImGui::NextColumn();
        ImGui::Separator();
        int count = 0;
        for (int i = 0; count < 10 && i <= seek_cursor; i++)
        {
            sim_State state_i = HISTORY_STATE[seek_cursor-i];
            sim_Command cmd_i = HISTORY_CMD[seek_cursor-i];
            if (cmd_i.type == sim_CommandType_NoCommand)
                continue;
            char label[32];
            sprintf(label, "%.2f", state_i.elapsed_time);
            ImGui::Selectable(label, false,
                              ImGuiSelectableFlags_SpanAllColumns);
            ImGui::NextColumn();
            switch (cmd_i.type)
            {
                case sim_CommandType_NoCommand:
                {
                    ImGui::Text("Nothing"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                } break;
                case sim_CommandType_LandInFrontOf:
                {
                    ImGui::Text("Land 180"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("%d", cmd_i.i); ImGui::NextColumn();
                } break;
                case sim_CommandType_LandOnTopOf:
                {
                    ImGui::Text("Land 45"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("%d", cmd_i.i); ImGui::NextColumn();
                } break;
                case sim_CommandType_Track:
                {
                    ImGui::Text("Track"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                    ImGui::Text("%d", cmd_i.i); ImGui::NextColumn();
                } break;
                case sim_CommandType_Search:
                {
                    ImGui::Text("Search"); ImGui::NextColumn();
                    ImGui::Text("%.2f", cmd_i.x); ImGui::NextColumn();
                    ImGui::Text("%.2f", cmd_i.y); ImGui::NextColumn();
                    ImGui::Text("-"); ImGui::NextColumn();
                } break;
            }
            count++;
        }
        ImGui::Columns(1);
        ImGui::Separator();
    } // END COMMUNICATION

    // RECORDING GIFS
    if (ImGui::CollapsingHeader("Recording"))
    {
        flag_SetupRecord = true;
        if (ImGui::Button("Mark frame as begin"))
        {
            record_from = seek_cursor;
        }
        ImGui::SameLine();
        ImGui::Text("Record from: %d", record_from);
        if (ImGui::Button("Mark frame as end"))
        {
            record_to = seek_cursor;
        }
        ImGui::SameLine();
        ImGui::Text("Record to: %d", record_to);
        ImGui::InputInt("Frame skip", &record_frame_skip);

        ImGui::InputInt("Record width", &record_width);
        ImGui::InputInt("Record height", &record_height);
        if (record_width <= 0) record_width = mode.width;
        if (record_height <= 0) record_height = mode.height;

        ImGui::SliderFloat("Record x", &record_region_x, -1.0f, 1.0f);
        ImGui::SliderFloat("Record y", &record_region_y, -1.0f, 1.0f);
        ImGui::SliderFloat("Record scale", &record_region_scale, 0.0f, 2.0f);

        if (ImGui::Button("Start recording") && !flag_Recording)
            ImGui::OpenPopup("Save recording as?");
        if (ImGui::BeginPopupModal("Save recording as?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
        {
            persist char filename[1024];
            persist bool init_filename = true;
            if (init_filename)
            {
                sprintf(filename, "recording%u.gif", STATE.seed);
                init_filename = false;
            }
            ImGui::InputText("Filename", filename, sizeof(filename));
            ImGui::Separator();

            if (ImGui::Button("OK", ImVec2(120,0)))
            {
                flag_Recording = true;
                flag_Paused = false;
                seek_cursor = record_from-1;
                record_gif = jo_gif_start(filename, (short)record_width, (short)record_height, 0, 32);
                ImGui::CloseCurrentPopup();
            }
            ImGui::SameLine();
            if (ImGui::Button("Cancel", ImVec2(120,0)))
            {
                ImGui::CloseCurrentPopup();
            }
            ImGui::EndPopup();
        }

        if (ImGui::Button("Stop recording") && flag_Recording)
        {
            flag_Recording = false;
            flag_Paused = true;
            jo_gif_end(&record_gif);
        }

        if (record_from < 0) record_from = 0;
        if (record_from > HISTORY_LENGTH-1) record_from = HISTORY_LENGTH-1;
        if (record_to < record_from) record_to = record_from;
        if (record_to > HISTORY_LENGTH-1) record_to = HISTORY_LENGTH-1;
        if (record_frame_skip < 1) record_frame_skip = 1;
        ImGui::Separator();
    }
    else
    {
        flag_SetupRecord = false;
    } // END RECORDING GIFS

    // RESET AND SET SEED
    persist int custom_seed = 0;
    if (ImGui::Button("Reset"))
    {
        if (custom_seed > 0)
            STATE = sim_init((u32)custom_seed);
        else
            STATE = sim_init((u32)get_tick());
        HISTORY_LENGTH = 0;
        sim_Command cmd;
        cmd.type = sim_CommandType_NoCommand;
        add_history(cmd, STATE);
    }
    ImGui::SameLine();
    ImGui::InputInt("Seed", &custom_seed);
    // END RESET AND SET SEED

    // SAVE SIMULATION
    if (ImGui::Button("Save.."))
        ImGui::OpenPopup("Save as?");
    if (ImGui::BeginPopupModal("Save as?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
    {
        persist char filename[1024];
        persist bool init_filename = true;
        if (init_filename)
        {
            sprintf(filename, "simulation%u", STATE.seed);
            init_filename = false;
        }
        ImGui::InputText("Filename", filename, sizeof(filename));
        ImGui::Separator();

        if (ImGui::Button("OK", ImVec2(120,0)))
        {
            write_history(filename);
            ImGui::CloseCurrentPopup();
        }
        ImGui::SameLine();
        if (ImGui::Button("Cancel", ImVec2(120,0)))
        {
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndPopup();
    } // END SAVE SIMULATION

    ImGui::SameLine();

    // SAVE SINGLE SNAPSHOT
    persist bool init_snapshot_filename = true;
    if (ImGui::Button("Save snapshot.."))
        ImGui::OpenPopup("Save snapshot as?");
    if (ImGui::BeginPopupModal("Save snapshot as?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
    {
        persist char filename[1024];
        ImGui::TextWrapped("The filename is relative to the executable,"
                           "unless you write an absolute path.");
        if (init_snapshot_filename)
        {
            sprintf(filename, "snapshot%u-%u", STATE.seed, seek_cursor);
            init_snapshot_filename = false;
        }
        ImGui::InputText("Filename", filename, sizeof(filename));
        ImGui::Separator();

        if (ImGui::Button("OK", ImVec2(120,0)))
        {
            sim_Observed_State snapshot =
                sim_observe_state(HISTORY_STATE[seek_cursor]);
            printf("%.2f\n", snapshot.obstacle_q[0]);
            sim_write_snapshot(filename, snapshot);
            ImGui::CloseCurrentPopup();
        }
        ImGui::SameLine();
        if (ImGui::Button("Cancel", ImVec2(120,0)))
        {
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }
    else
    {
        init_snapshot_filename = true;
    } // END SAVE SIMULATION

    ImGui::SameLine();

    // LOAD SIMULATION
    if (ImGui::Button("Load.."))
        ImGui::OpenPopup("Load file?");
    if (ImGui::BeginPopupModal("Load file?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
    {
        persist char filename[1024];
        persist bool init_filename = true;
        if (init_filename)
        {
            sprintf(filename, "simulation%u", STATE.seed);
            init_filename = false;
        }
        ImGui::InputText("Filename", filename, sizeof(filename));
        ImGui::Separator();

        if (ImGui::Button("OK", ImVec2(120,0)))
        {
            read_history(filename);
            seek_cursor = 0;
            flag_Paused = true;
            ImGui::CloseCurrentPopup();
        }
        ImGui::SameLine();
        if (ImGui::Button("Cancel", ImVec2(120,0)))
        {
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndPopup();
    } // END LOAD SIMULATION

    ImGui::Render();
} // END gui_tick