コード例 #1
0
ファイル: __init__.py プロジェクト: MeyerJon/ParticleSim
def load_from_json(sim, fname="sim"):
    """ Loads a simulation state. """

    fname = get_file_path(fname, "json")

    if not os.path.exists(fname):
        Logger.log_error("File not found: '{}'. Can't load.".format(fname))
        return

    data = dict()
    with open(fname, 'r') as savefile:
        data = json.load(savefile)

    # Clear previous state
    sim.entities.clear()

    # Construct sim state
    sim.lifetime = data["lifetime"]

    for e in data["particles"]:

        p = particle_factory.create_particle(e)
        if p is not None:
            sim.add_entity(p)
        else:
            Logger.log_warning("Loading particle failed.")
コード例 #2
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def toggle_debug_view(particle):
    if particle is None:
        return
    try:
        particle.debug_view = not particle.debug_view
    except:
        Logger.log_warning("Can't toggle debug view of selected entity.")
コード例 #3
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def delete_particle(particle):

    if particle is None:
        return

    particle.mfd = True
    Logger.log_custom("control", "Deleting particle.")
コード例 #4
0
ファイル: __init__.py プロジェクト: MeyerJon/ParticleSim
def save_to_json(sim, fname="sim"):
    """ Saves a simulation's state as a .json file. """

    fname = get_file_path(fname, "json")

    with open(fname, 'w') as savefile:

        # Collect all data to be saved
        data = {"lifetime": sim.lifetime, "particles": list()}

        # Go over each entity and save its properties
        for e in sim.entities:

            if issubclass(type(e), particle.ForceParticle):
                try:
                    p_data = dict()
                    p_data["type"] = str(type(e))
                    p_data["pos"] = e.pos
                    p_data["velocity"] = e.velocity
                    p_data["mass"] = e.mass
                    p_data["size"] = e.size
                    p_data["can_move"] = e._can_move
                    p_data["paused"] = e.paused
                    data["particles"].append(p_data)
                except AttributeError as e:
                    Logger.log_warning(
                        "Corrupt particle. Can't save particle.")
                    Logger.log_exception(e)
                    continue

        # Dump data to json
        json.dump(data, savefile)
コード例 #5
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def set_global_particle_radius(sim, r):
    """ Sets all PrimordialParticle's radii. Note: This is rather costly """

    for e in sim.entities:
        try:
            e.radius = r
        except AttributeError:
            Logger.log_warning("Can't set radius of entity: {}".format(e))
    Logger.log_custom("control", "Set global particle radius to {}.".format(r))
コード例 #6
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def set_global_particle_velocity(sim, v):

    for e in sim.entities:
        try:
            e.velocity = [v, v]
        except AttributeError:
            Logger.log_warning("Can't set velocity of entity {}".format(e))
    Logger.log_custom("control",
                      "Set global particle velocity to {}.".format(v))
コード例 #7
0
 def add_state(self, s, ix=None):
     if s not in self.S:
         if ix is None:
             self.S.append(s)
         else:
             try:
                 self.S.insert(ix, s)
             except:
                 Logger.log_warning(
                     "Can't insert state at position {}.".format(ix))
コード例 #8
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def toggle_pause(target):

    target.paused = (not target.paused)

    log_msg = str(type(target))
    if target.paused:
        log_msg += " paused."
    else:
        log_msg += " unpaused."
    Logger.log_custom("control", log_msg)
コード例 #9
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def toggle_trail(particle):
    if particle is None:
        return
    try:
        particle.draw_trail_points = not particle.draw_trail_points
        if particle.draw_trail_points:
            # Clear previous trail if turning it back on
            particle.trail_points.clear()
    except AttributeError:
        Logger.log_warning("Can't draw trail of selected entity.")
コード例 #10
0
ファイル: __init__.py プロジェクト: MeyerJon/ParticleSim
def create_data_folder():
    """ Creates the data folder if it doesn't exist. """
    path = "./data"  # default folder
    try:
        path = CONFIG["data_folder"]
    except KeyError:
        pass

    if not os.path.exists(path):
        os.mkdir(path)
        Logger.log_system("Created data directory.")
コード例 #11
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def cycle_trail_length(particle, increase=False):

    if particle is None:
        return

    try:
        old = particle.trail_points.limit
        inc = -1 * (int(math.log10(old)) + 1)
        if increase:
            inc *= -1  # Make increment positive
            particle.trail_points.set_limit(old + inc)
    except AttributeError:
        Logger.log_warning("Cannot change trail length of selected entity.")
コード例 #12
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def cycle_trail_density(particle, increase=False):
    if particle is None:
        return

    inc = -1
    if increase:
        inc = 1

    try:
        new = particle.trail_points_interval + inc
        if new > 0:
            particle.trail_points_interval = new
    except:
        Logger.log_warning("Can't adjust trail density of selected entity.")
コード例 #13
0
    def calculate_type_mod(self, e):

        result = 0
        e_type = type(e)

        try:
            result = self.interacting_types[e_type]
        except KeyError:
            # This shouldn't be reachable, but let's be safe
            Logger.log_warning(
                "Trying to calculate mod for unknown type '{}'.".format(
                    e_type))

        return result
コード例 #14
0
 def calculate_reflect_force(self, e):
     try:
         return self.interacting_types[type(e)]
     except KeyError:
         # Add reflection mod / 0 for this new type
         F = 0
         t_self = type(self)
         t_e = type(e)
         if t_self in e.interacting_types:
             F = e.interacting_types[t_self]
         self.interacting_types[t_e] = F
         Logger.log_info("Discovered unknown type {} -> {}".format(
             t_self, t_e))
         return F
コード例 #15
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def set_tick_speed(controller, symbol):

    old_tps = controller.ticks_per_secs
    max_tps = 400
    try:
        max_tps = CONFIG["max_TPS"]
    except KeyError:
        pass

    if symbol == key.UP:
        new_tps = min(old_tps * 2.0, max_tps)
    else:
        new_tps = max(1, old_tps / 2.0)

    pyglet.clock.unschedule(controller.tick)
    pyglet.clock.schedule_interval(controller.tick, 1.0 / new_tps)
    controller.ticks_per_secs = new_tps
    Logger.log_system("Set TPS to {}.".format(controller.ticks_per_secs))
コード例 #16
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def change_particle_velocity(symbol, particle):
    # Changes a particle's velocity based on the key pressed

    if particle is None:
        return

    speedmod = 0.1
    mod = 1
    if symbol == key.W:
        # Slow down, fella
        mod = (1 - speedmod)
    elif symbol == key.C:
        # Hurry up, buster
        mod = (1 + speedmod)
    elif symbol == key.X:
        # It's time to stop
        mod = 0

    speed_incr = (0, 0)
    step = 0.0001
    if symbol == key.LEFT:
        speed_incr = (-step, 0)
    elif symbol == key.RIGHT:
        speed_incr = (step, 0)
    elif symbol == key.UP:
        speed_incr = (0, step)
    elif symbol == key.DOWN:
        speed_incr = (0, -step)

    try:
        v_old = particle.velocity
        particle.velocity = ((v_old[0] * mod) + speed_incr[0],
                             (v_old[1] * mod) + speed_incr[1])
    except AttributeError:
        Logger.log_warning(
            "Selected entity is not a particle. Can't change velocity.")
コード例 #17
0
ファイル: Particles.py プロジェクト: MeyerJon/ParticleSim
import Particles
from Particles.utils import Logger

import datetime, cProfile

# Time app
start_time = datetime.datetime.now()

# Initialize logfile
Logger.clear_logfile()
Logger.log("Started at " + str(start_time))

# Start the simulation
Particles.run_app("./config.json")
#cProfile.run("Particles.run_app()")

# Finish up logfile
end_time = datetime.datetime.now()
Logger.log("Quit at " + str(end_time))
Logger.log("Ran for {}".format(str(end_time - start_time)))
コード例 #18
0
def run_app(config=None):

    # Setup model & controller
    sim = simulation.setup()
    keyboard = pyglet.window.key.KeyStateHandler()
    controller = sim_control.SimController(sim, keyboard)

    # Add handlers
    app.win.push_handlers(controller)
    app.win.push_handlers(keyboard)

    # Profiling
    Profiler.make_profiler_category("draw_times")
    Profiler.make_profiler_category("tick_times")

    # Logger verbose level
    default_verbose = 3
    if "verbose_level" in app.CONFIG:
        default_verbose = app.CONFIG["verbose_level"]
    Logger.set_verbose_level(default_verbose)

    fps_counter = None
    if "show_FPS" in app.CONFIG and app.CONFIG["show_FPS"]:
        fps_counter = pyglet.window.FPSDisplay(app.win)

    # Schedule initial simulation speed
    ticks_per_sec = 25.0
    pyglet.clock.schedule_interval(controller.tick, 1 / ticks_per_sec)

    # Cap FPS
    max_fps = 120
    if "max_FPS" in app.CONFIG:
        max_fps = app.CONFIG["max_FPS"]
    pyglet.clock.set_fps_limit(max_fps)

    # Draw event
    @app.win.event
    def on_draw():
        starttime = time.time()
        app.win.clear()
        sim.draw()
        controller.draw()
        Profiler.add_profiler_data("draw_times", time.time() - starttime)
        if fps_counter: fps_counter.draw()

    # Generate history (run the simulation without opening the window)
    # This is useful to save time on drawing
    history_length = 0
    if history_length > 0:
        paused_state = sim.paused
        Logger.log_system(
            "Generating {} ticks of history.".format(history_length))
        starttime = time.time()
        sim.paused = False
        for _ in range(history_length):
            controller.tick()
        sim.paused = paused_state
        Logger.log_system("Finished generating history. ({} s)".format(
            (time.time() - starttime)))

    # Main app loop
    pyglet.app.run()

    # Collect & log some stats
    post_run_stats(controller, sim)

    return
コード例 #19
0
ファイル: controls.py プロジェクト: MeyerJon/ParticleSim
def toggle_particle_movable(particle):

    try:
        particle._can_move = not particle._can_move
    except AttributeError:
        Logger.log_warning("Can't toggle movability of '{}.'".format(particle))
コード例 #20
0
def post_run_stats(controller, sim):

    Logger.log("<----------------->")
    Logger.log("> Execution stats")

    Logger.log(">> Simulation lifespan: {} ticks".format(sim.lifetime))

    avg_draw = Profiler.get_numeric_category_avg("draw_times")
    if avg_draw is not None:
        Logger.log(">> Avg. drawing time: {} ms".format(avg_draw * 1000))
    avg_tick = Profiler.get_numeric_category_avg("tick_times")
    if avg_tick is not None:
        Logger.log(">> Avg. tick time: {} ms".format(avg_tick * 1000))

    Logger.log("<----------------->")
コード例 #21
0
ファイル: sim_control.py プロジェクト: MeyerJon/ParticleSim
    def on_key_press(self, symbol, modifiers):
        # Handle key press

        # Mode switch
        if symbol in [key.M]:
            self.mode = ModeEnum((self.mode.value + 1) % len(list(ModeEnum)))
            Logger.log_custom("control",
                              "Changed mode to {}.".format(self.mode))

        if self.mode == ModeEnum.SELECT:

            if symbol == key.P:
                if self._cur_selected is None:
                    controls.toggle_pause(self.sim)
                else:
                    controls.toggle_pause(self._cur_selected)

            if symbol in [key.UP, key.DOWN
                          ] and modifiers == 18:  # 16 (base) + 2 (ctrl)
                controls.set_tick_speed(self, symbol)

            if symbol == key.H:
                if self._cur_selected is None:
                    self._ui.visible = not self._ui.visible
                else:
                    controls.toggle_debug_view(self._cur_selected)

            if symbol == key.T:
                if self._cur_selected is not None:
                    controls.toggle_trail(self._cur_selected)

            if symbol == key.SPACE:
                if self._cur_selected is not None:
                    controls.toggle_particle_movable(self._cur_selected)

            if symbol == key.S and modifiers == 18:  # CRTL+S
                Logger.log_custom("control", "Saving current state...")
                persistence.save_to_json(self.sim)
                Logger.log_custom("control", "Finished saving.")

            if symbol == key.L and modifiers == 18:  # CRTL+L
                Logger.log_custom("control", "Loading state...")
                persistence.load_from_json(self.sim)
                Logger.log_custom("control", "Finished loading.")

        if self.mode == ModeEnum.DESTROY:

            if symbol == key.BACKSPACE:
                controls.delete_particle(self._cur_selected)
                self._cur_selected = None

        if self.mode == ModeEnum.CREATE:

            # Cycling creatable types
            if symbol == key.LEFT:
                self.cur_creation_index = (self.cur_creation_index + 1) % len(
                    self.creatable_types)
                Logger.log_custom(
                    "control", "Changed creation type to {}.".format(
                        self.creatable_types[self.cur_creation_index]))
            if symbol == key.RIGHT:
                self.cur_creation_index = ((self.cur_creation_index - 1) %
                                           len(self.creatable_types))
                Logger.log_custom(
                    "control", "Changed creation type to {}.".format(
                        self.creatable_types[self.cur_creation_index]))
コード例 #22
0
def create_particle(data):
    """ Accepts data and creates particle according to it. """

    # Get particle type
    type_raw = None
    try:
        type_raw = data["type"]
    except KeyError as ke:
        Logger.log_warning("No particle type data. Can't spawn particle.")
        Logger.log_exception(ke)
        return None

    t = type_raw
    if type(type_raw) is str:
        # Get actual class reference
        t = get_particle_type(type_raw)

    if t is None:
        Logger.log_warning("Unrecognized particle type. Can't spawn particle.")
        return None

    # Construct particle
    p = None
    try:
        pos = data["pos"]
        p = t(pos[0], pos[1])
    except KeyError as ke:
        Logger.log_warning("Incomplete particle data. Can't spawn particle.")
        Logger.log_exception(ke)
        return None

    # Set particle attributes
    try:
        p.mass = data["mass"]
        p.velocity = data["velocity"]
        p.size = data["size"]
        p._can_move = data["can_move"]
        p.paused = data["paused"]
    except KeyError as ke:
        Logger.log_info("Missing particle data.")
        Logger.log_exception(ke)

    return p