Skip to content

Commit 2d793d2

Browse files
committed
style UI issues
1 parent 0d1f38f commit 2d793d2

12 files changed

Lines changed: 395 additions & 259 deletions

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.22)
22

3-
project(BeatCrafter VERSION 0.1.0)
3+
project(BeatCrafter VERSION 0.1.1)
44
set(CMAKE_CXX_STANDARD 17)
55
set(CMAKE_CXX_STANDARD_REQUIRED ON)
66

@@ -29,7 +29,7 @@ juce_add_plugin(BeatCrafter
2929
NEEDS_MIDI_OUTPUT TRUE
3030
PRODUCES_MIDI_OUTPUT TRUE
3131
PRODUCT_NAME "BeatCrafter"
32-
BUNDLE_ID "com.beatcrafter.beatcrafter"
32+
BUNDLE_ID "com.innermost47.beatcrafter"
3333
)
3434

3535
target_sources(BeatCrafter
@@ -64,6 +64,7 @@ juce_add_binary_data(BeatCrafterData
6464
resources/phosphor/ear.svg
6565
resources/phosphor/link-simple-break.svg
6666
resources/phosphor/wave-sine.svg
67+
resources/phosphor/number-three.svg
6768
)
6869

6970
set_target_properties(BeatCrafterData PROPERTIES
Lines changed: 1 addition & 0 deletions
Loading

src/Core/PatternEngine.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,14 @@ namespace BeatCrafter
121121
double ppqPosition = posInfo.getPpqPosition().orFallback(0.0);
122122
int currentMeasure = static_cast<int>(ppqPosition / 4.0);
123123
double beatsPerSecond = bpm / 60.0;
124-
double sixteenthsPerSecond = beatsPerSecond * 4.0;
125-
samplesPerStep = static_cast<int>(sampleRate / sixteenthsPerSecond);
124+
double stepsPerBeat = perfParams.tripletMode ? 3.0 : 4.0;
125+
double stepsPerSecond = beatsPerSecond * stepsPerBeat;
126+
samplesPerStep = static_cast<int>(sampleRate / stepsPerSecond);
126127
auto& pattern = *slots[activeSlot];
127128
int patternLength = pattern.getLength();
128-
double ppqPerStep = 0.25;
129-
int currentStepFromPPQ = static_cast<int>(ppqPosition / ppqPerStep) % patternLength;
129+
double ppqPerStep = perfParams.tripletMode ? (1.0 / 3.0) : 0.25;
130+
int effectiveLength = perfParams.tripletMode ? 12 : patternLength;
131+
int currentStepFromPPQ = static_cast<int>(ppqPosition / ppqPerStep) % effectiveLength;
130132
updateSurpriseMe(currentMeasure, ppqPosition);
131133
if (currentStepFromPPQ != pattern.getCurrentStep() ||
132134
(currentStepFromPPQ == 0 && ppqPosition < 0.1))

src/Core/PatternEngine.h

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,26 @@ namespace BeatCrafter
1717
bool humanizeEnabled = true;
1818
float humanizeAmount = 0.08f;
1919
float omitChance = 0.05f;
20-
20+
bool tripletMode = false;
2121
bool surpriseMeEnabled = false;
2222
float surpriseMeRange = 0.15f;
2323
};
2424

2525
PatternEngine();
2626
~PatternEngine() = default;
2727

28-
Pattern &getCurrentPattern() { return slots[activeSlot] ? *slots[activeSlot] : dummyPattern; }
29-
const Pattern &getCurrentPattern() const { return *slots[activeSlot]; }
30-
const Pattern *getDisplayPattern() const { return &intensifiedPatternCache; }
31-
Pattern *getCurrentBasePattern() { return slots[activeSlot].get(); }
32-
Pattern *getSlot(int index) { return (index >= 0 && index < 8 && slots[index]) ? slots[index].get() : nullptr; }
28+
Pattern& getCurrentPattern() { return slots[activeSlot] ? *slots[activeSlot] : dummyPattern; }
29+
const Pattern& getCurrentPattern() const { return *slots[activeSlot]; }
30+
const Pattern* getDisplayPattern() const { return &intensifiedPatternCache; }
31+
Pattern* getCurrentBasePattern() { return slots[activeSlot].get(); }
32+
Pattern* getSlot(int index) { return (index >= 0 && index < 8 && slots[index]) ? slots[index].get() : nullptr; }
3333

3434
PerformanceParams perfParams;
3535

3636
void loadPatternToSlot(std::unique_ptr<Pattern> pattern, int slot);
3737
void generateNewPattern(StyleType style, float complexity = 0.5f);
3838
void generateNewPatternForSlot(int slot, StyleType style, float complexity = 0.5f);
39-
Pattern applyIntensity(const Pattern &basePattern, float intensity) const;
39+
Pattern applyIntensity(const Pattern& basePattern, float intensity) const;
4040

4141
void switchToSlot(int slot, bool immediate = false, float intensity = -1.0f);
4242
int getActiveSlot() const { return activeSlot; }
@@ -87,10 +87,10 @@ namespace BeatCrafter
8787
void resetToStart();
8888
bool getIsPlaying() const { return isPlaying; }
8989

90-
void processBlock(juce::MidiBuffer &midiMessages,
91-
int numSamples,
92-
double sampleRate,
93-
const juce::AudioPlayHead::PositionInfo &posInfo);
90+
void processBlock(juce::MidiBuffer& midiMessages,
91+
int numSamples,
92+
double sampleRate,
93+
const juce::AudioPlayHead::PositionInfo& posInfo);
9494

9595
private:
9696
std::array<std::unique_ptr<Pattern>, 8> slots;
@@ -104,7 +104,7 @@ namespace BeatCrafter
104104
mutable bool intensityCacheValid = false;
105105
mutable float lastCachedIntensity = -1.0f;
106106
mutable int lastCachedSlot = -1;
107-
Pattern dummyPattern{"Empty"};
107+
Pattern dummyPattern{ "Empty" };
108108

109109
float currentIntensity = -1.0f;
110110
float currentLiveJamIntensity = 0.5f;
@@ -126,16 +126,16 @@ namespace BeatCrafter
126126
juce::Random liveJamRandom;
127127
int stepsSinceLastJam = 0;
128128

129-
std::atomic<int> pendingImmediateSlot{-1};
129+
std::atomic<int> pendingImmediateSlot{ -1 };
130130

131-
void generateMidiForStep(juce::MidiBuffer &midiMessages,
132-
int samplePosition,
133-
const Pattern &pattern,
134-
int stepIndex);
135-
void applyComplexityToPattern(Pattern &pattern, StyleType style, float complexity);
136-
void addLiveJamElements(Pattern &pattern, int stepIndex, float intensity);
137-
void sendAllNotesOff(juce::MidiBuffer &midiMessages);
138-
void applyHumanization(Pattern &pattern, int stepIndex);
131+
void generateMidiForStep(juce::MidiBuffer& midiMessages,
132+
int samplePosition,
133+
const Pattern& pattern,
134+
int stepIndex);
135+
void applyComplexityToPattern(Pattern& pattern, StyleType style, float complexity);
136+
void addLiveJamElements(Pattern& pattern, int stepIndex, float intensity);
137+
void sendAllNotesOff(juce::MidiBuffer& midiMessages);
138+
void applyHumanization(Pattern& pattern, int stepIndex);
139139
void updateSurpriseMe(int currentMeasure, double ppqPosition);
140140
};
141141
}

src/GUI/PatternGrid.cpp

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,48 @@ namespace BeatCrafter {
1313

1414
void PatternGrid::setPattern(const Pattern* pattern) {
1515
currentPattern = pattern;
16+
bufferDirty = true;
1617
repaint();
1718
}
1819

1920
void PatternGrid::setPatternEngine(PatternEngine* engine) {
2021
patternEngine = engine;
2122
}
2223

23-
void PatternGrid::paint(juce::Graphics& g) {
24+
void PatternGrid::paint(juce::Graphics& g)
25+
{
2426
if (!lookAndFeel)
2527
lookAndFeel = dynamic_cast<ModernLookAndFeel*>(&getLookAndFeel());
2628

27-
drawBackground(g);
28-
drawGrid(g);
29+
if (offscreenBuffer.isNull()
30+
|| offscreenBuffer.getWidth() != getWidth()
31+
|| offscreenBuffer.getHeight() != getHeight()
32+
|| bufferDirty)
33+
{
34+
offscreenBuffer = juce::Image(
35+
juce::Image::ARGB, getWidth(), getHeight(), true);
36+
juce::Graphics bg(offscreenBuffer);
37+
38+
drawBackground(bg);
39+
drawGrid(bg);
40+
if (currentPattern) {
41+
drawSteps(bg);
42+
drawPlayhead(bg);
43+
}
44+
drawTrackLabels(bg);
45+
drawStepNumbers(bg);
2946

30-
if (currentPattern) {
31-
drawSteps(g);
32-
drawPlayhead(g);
47+
bufferDirty = false;
3348
}
3449

35-
drawTrackLabels(g);
36-
drawStepNumbers(g);
50+
g.drawImageAt(offscreenBuffer, 0, 0);
51+
}
52+
53+
void PatternGrid::markDirty()
54+
{
55+
bufferDirty = true;
56+
if (!isTimerRunning())
57+
repaint();
3758
}
3859

3960
void PatternGrid::resized() {
@@ -42,13 +63,15 @@ namespace BeatCrafter {
4263
int numTracks = currentPattern ? currentPattern->getNumTracks() : 8;
4364
cellWidth = (bounds.getWidth() - headerWidth) / static_cast<float>(numSteps);
4465
cellHeight = (bounds.getHeight() - headerHeight) / static_cast<float>(numTracks);
66+
bufferDirty = true;
4567
}
4668

4769
void PatternGrid::timerCallback() {
4870
if (patternEngine) {
4971
int newPlayhead = patternEngine->getCurrentStep();
5072
if (newPlayhead != playheadPosition) {
5173
playheadPosition = newPlayhead;
74+
bufferDirty = true;
5275
repaint();
5376
}
5477
}

src/GUI/PatternGrid.h

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,44 @@
66

77
namespace BeatCrafter {
88

9-
class PatternGrid : public juce::Component,
10-
public juce::Timer
11-
{
12-
public:
13-
PatternGrid();
14-
~PatternGrid() override;
15-
16-
void setPattern(const Pattern* pattern);
17-
void setPatternEngine(PatternEngine* engine);
18-
19-
void paint(juce::Graphics&) override;
20-
void resized() override;
21-
void timerCallback() override;
22-
23-
private:
24-
const Pattern* currentPattern = nullptr;
25-
PatternEngine* patternEngine = nullptr;
26-
ModernLookAndFeel* lookAndFeel = nullptr;
27-
28-
float cellWidth = 0.0f;
29-
float cellHeight = 0.0f;
30-
int headerWidth = 80;
31-
int headerHeight = 20;
32-
int playheadPosition = -1;
33-
34-
juce::Rectangle<float> getStepBounds(int track, int step) const;
35-
36-
void drawBackground(juce::Graphics&);
37-
void drawGrid(juce::Graphics&);
38-
void drawSteps(juce::Graphics&);
39-
void drawPlayhead(juce::Graphics&);
40-
void drawTrackLabels(juce::Graphics&);
41-
void drawStepNumbers(juce::Graphics&);
42-
43-
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PatternGrid)
44-
};
9+
class PatternGrid : public juce::Component,
10+
public juce::Timer
11+
{
12+
public:
13+
PatternGrid();
14+
~PatternGrid() override;
15+
16+
void setPattern(const Pattern* pattern);
17+
void setPatternEngine(PatternEngine* engine);
18+
19+
void paint(juce::Graphics&) override;
20+
void resized() override;
21+
void timerCallback() override;
22+
void markDirty();
23+
24+
private:
25+
const Pattern* currentPattern = nullptr;
26+
PatternEngine* patternEngine = nullptr;
27+
ModernLookAndFeel* lookAndFeel = nullptr;
28+
29+
float cellWidth = 0.0f;
30+
float cellHeight = 0.0f;
31+
int headerWidth = 80;
32+
int headerHeight = 20;
33+
int playheadPosition = -1;
34+
35+
juce::Image offscreenBuffer;
36+
bool bufferDirty = true;
37+
38+
juce::Rectangle<float> getStepBounds(int track, int step) const;
39+
40+
void drawBackground(juce::Graphics&);
41+
void drawGrid(juce::Graphics&);
42+
void drawSteps(juce::Graphics&);
43+
void drawPlayhead(juce::Graphics&);
44+
void drawTrackLabels(juce::Graphics&);
45+
void drawStepNumbers(juce::Graphics&);
46+
47+
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PatternGrid)
48+
};
4549
}

0 commit comments

Comments
 (0)