aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/mptrack/UpdateHints.h
blob: 118ac5b7e380a8674e22ab56e40e27a53a525122 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*
 * UpdateHints.h
 * -------------
 * Purpose: Hint type and abstraction class for passing around hints between module views.
 * Notes  : (currently none)
 * Authors: OpenMPT Devs
 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 */


#pragma once

#include "openmpt/all/BuildSettings.hpp"

#include "openmpt/base/FlagSet.hpp"
#include "../soundlib/Snd_defs.h"

OPENMPT_NAMESPACE_BEGIN

// Mutually exclusive hint categories
enum HintCategory
{
	HINTCAT_GLOBAL		= 0,	// Not a real category, since all other categories can be combined with this
	HINTCAT_GENERAL		= 0,
	HINTCAT_PATTERNS	= 1,
	HINTCAT_SAMPLES		= 2,
	HINTCAT_INSTRUMENTS	= 3,
	HINTCAT_SEQUENCE	= 4,
	HINTCAT_PLUGINS		= 5,
	HINTCAT_COMMENTS	= 6,

	NUM_HINTCATS
};

enum HintType
{
	// Hints that can be combined with any other hints (no parameter)
	HINT_NONE			= 0x00,	// No specific hint
	HINT_MODTYPE		= 0x01,	// Module type has changed. Generally this will force most things to update.
	HINT_MPTOPTIONS		= 0x02,	// Some OpenMPT options (e.g. colours) have changed which might require stuff to be redrawn.
	HINT_UNDO			= 0x04,	// Undo state information has changed

	HINT_ALLGLOBAL = HINT_MODTYPE | HINT_MPTOPTIONS | HINT_UNDO,

	// From here: Mutually exclusive hint categories

	// General module setting hints (GeneralHint)
	HINT_MODGENERAL		= 0x10,	// General global module settings have changed
	HINT_MODCHANNELS	= 0x20,	// Module channel settings have changed (e.g. channel volume). Parameter: Channel ID
	HINT_TUNINGS		= 0x40,	// Tuning collection was updated
	// Pattern-specific hints (PatternHint)
	HINT_PATTERNDATA	= 0x10,	// Pattern data has changed. Parameter: Pattern ID (0 = all patterns)
	HINT_PATTERNROW		= 0x20,	// A row of the currently edited pattern has changed. Parameter: Row number
	HINT_PATNAMES		= 0x40,	// Pattern names have changed. Parameter: Pattern ID (0 = all patterns)
	// Sample-specific hints (SampleHint)
	HINT_SAMPLEINFO		= 0x10,	// Sample properties have changed. Parameter: Sample ID (0 = all samples)
	HINT_SAMPLEDATA		= 0x20,	// Sample waveform has changed. Parameter: Sample ID (0 = all samples)
	HINT_SMPNAMES		= 0x40,	// Sample name has changed. Parameter: Sample ID (0 = all samples)
	// Instrument-specific hints (InstrumentHint)
	HINT_INSTRUMENT		= 0x10,	// Instrument properties have changed. Parameter: Instrument ID (0 = all instruments)
	HINT_ENVELOPE		= 0x20,	// An instrument envelope has changed. Parameter: Instrument ID (0 = all instruments)
	HINT_INSNAMES		= 0x40,	// Instrument name has changed. Parameter: Instrument ID (0 = all instruments)
	// Sequence-specific hints (SequenceHint)
	HINT_MODSEQUENCE	= 0x10,	// The pattern sequence has changed.
	HINT_SEQNAMES		= 0x20,	// Sequence names have changed. Parameter: Sequence ID (0 = all sequences)
	HINT_RESTARTPOS		= 0x40,	// Restart position has changed. Parameter: Sequence ID (0 = all sequences)
	// Plugin-specific hints (PluginHint)
	HINT_MIXPLUGINS		= 0x10,	// Plugin properties have changed. Parameter: Plugin ID (0 = all plugins, 1 = first plugin)
	HINT_PLUGINNAMES	= 0x20,	// Plugin names have changed. Parameter: Plugin ID (0 = all plugins, 1 = first plugin)
	HINT_PLUGINPARAM	= 0x40,	// Plugin parameter has changed. Parameter: Plugin ID (0 = all plugins, 1 = first plugin)
	// Comment text hints (CommentHint)
	HINT_MODCOMMENTS	= 0x10,	// Module comment text has changed
};
DECLARE_FLAGSET(HintType)

struct UpdateHint
{
protected:
	using store_t = uint32;
	union
	{
		struct
		{
			store_t type     : 7;	// All HintType flags must fit into this.
			store_t category : 3;	// All HintCategory types must fit into this.
			store_t item     : 22;
		};
		store_t rawData;
	};
	
	UpdateHint(HintCategory category_, store_t item_ = 0) : type(HINT_NONE), category(category_), item(item_)
	{
		static_assert(sizeof(UpdateHint) == sizeof(store_t), "Internal UpdateHint size inconsistency");
		static_assert(sizeof(UpdateHint) <= sizeof(LPARAM), "Update hints are currently tunnelled through LPARAMs in MFC");
		MPT_ASSERT(static_cast<HintCategory>(category) == category_);
		MPT_ASSERT(UpdateHint::item == item);
	}

	template<typename T>
	MPT_FORCEINLINE T GetData() const { return static_cast<T>(item); }

public:
	UpdateHint() : type(HINT_NONE), category(HINTCAT_GLOBAL), item(0) { }

	template<typename T>
	MPT_FORCEINLINE UpdateHint &SetData(T i) { item = i; MPT_ASSERT(item == i); return *this; }

	MPT_FORCEINLINE HintCategory GetCategory() const { return static_cast<HintCategory>(category); }
	MPT_FORCEINLINE FlagSet<HintType> GetType() const { return FlagSet<HintType>(static_cast<FlagSet<HintType>::store_type>(type)); }

	// CModDoc hint tunnelling
	static MPT_FORCEINLINE UpdateHint FromLPARAM(LPARAM rawData) { UpdateHint hint; hint.rawData = static_cast<store_t>(rawData); return hint; }
	MPT_FORCEINLINE LPARAM AsLPARAM() const { return rawData; }

	// Discard any hints that don't belong to class T.
	template<typename T>
	MPT_FORCEINLINE T ToType() const
	{
		T hint = static_cast<const T &>(*this);
		if(T::classCategory != static_cast<HintCategory>(category))
		{
			hint.type &= HINT_ALLGLOBAL;
			hint.item = 0;
		}
		return hint;
	}

	// Set global hint flags
	MPT_FORCEINLINE UpdateHint &ModType() { type |= HINT_MODTYPE; return *this; }
	MPT_FORCEINLINE UpdateHint &MPTOptions() { type |= HINT_MPTOPTIONS; return *this; }
	MPT_FORCEINLINE UpdateHint &Undo() { type |= HINT_UNDO; return *this; }
};

struct GeneralHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_GENERAL;
	GeneralHint() : UpdateHint(classCategory, 0) { }
	GeneralHint(CHANNELINDEX channel) : UpdateHint(classCategory, 1 + channel) { }
	MPT_FORCEINLINE GeneralHint &General() { type |= HINT_MODGENERAL; return *this; }
	MPT_FORCEINLINE GeneralHint &Channels() { type |= HINT_MODCHANNELS; return *this; }
	MPT_FORCEINLINE GeneralHint &Tunings() { type |= HINT_TUNINGS; return *this; }

	MPT_FORCEINLINE CHANNELINDEX GetChannel() const { return item ? static_cast<CHANNELINDEX>(item - 1) : CHANNELINDEX_INVALID; }
};

struct PatternHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
	PatternHint(PATTERNINDEX item = 0) : UpdateHint(classCategory, item) { }
	MPT_FORCEINLINE PatternHint &Data() { type |= HINT_PATTERNDATA; return *this; }
	MPT_FORCEINLINE PatternHint &Names() { type |= HINT_PATNAMES; return *this; }

	PATTERNINDEX GetPattern() const { return GetData<PATTERNINDEX>(); }
};

struct RowHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_PATTERNS;
	RowHint(ROWINDEX item = 0) : UpdateHint(classCategory, item) { type = HINT_PATTERNROW; }

	MPT_FORCEINLINE ROWINDEX GetRow() const { return GetData<ROWINDEX>(); }
};

struct SampleHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_SAMPLES;
	SampleHint(SAMPLEINDEX item = 0) : UpdateHint(classCategory, item) { }
	MPT_FORCEINLINE SampleHint &Info() { type |= HINT_SAMPLEINFO; return *this; }
	MPT_FORCEINLINE SampleHint &Data() { type |= HINT_SAMPLEDATA; return *this; }
	MPT_FORCEINLINE SampleHint &Names() { type |= HINT_SMPNAMES; return *this; }

	MPT_FORCEINLINE SAMPLEINDEX GetSample() const { return GetData<SAMPLEINDEX>(); }
};

struct InstrumentHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_INSTRUMENTS;
	InstrumentHint(INSTRUMENTINDEX item = 0) : UpdateHint(classCategory, item) { }
	MPT_FORCEINLINE InstrumentHint &Info() { type |= HINT_INSTRUMENT; return *this; }
	MPT_FORCEINLINE InstrumentHint &Envelope() { type |= HINT_ENVELOPE; return *this; }
	MPT_FORCEINLINE InstrumentHint &Names() { type |= HINT_INSNAMES; return *this; }

	MPT_FORCEINLINE INSTRUMENTINDEX GetInstrument() const { return GetData<INSTRUMENTINDEX>(); }
};

struct SequenceHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_SEQUENCE;
	SequenceHint(SEQUENCEINDEX item = 0) : UpdateHint(classCategory, item) { }
	MPT_FORCEINLINE SequenceHint &Data() { type |= HINT_MODSEQUENCE; return *this; }
	MPT_FORCEINLINE SequenceHint &Names() { type |= HINT_SEQNAMES; return *this; }
	MPT_FORCEINLINE SequenceHint &RestartPos() { type |= HINT_RESTARTPOS; return *this; }

	MPT_FORCEINLINE SEQUENCEINDEX GetSequence() const { return GetData<SEQUENCEINDEX>(); }
};

struct PluginHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_PLUGINS;
	PluginHint(PLUGINDEX item = 0) : UpdateHint(classCategory, item) { }
	MPT_FORCEINLINE PluginHint &Info() { type |= HINT_MIXPLUGINS; return *this; }
	MPT_FORCEINLINE PluginHint &Names() { type |= HINT_PLUGINNAMES; return *this; }
	MPT_FORCEINLINE PluginHint &Parameter() { type |= HINT_PLUGINPARAM; return *this; }

	MPT_FORCEINLINE PLUGINDEX GetPlugin() const { return GetData<PLUGINDEX>(); }
};

struct CommentHint : public UpdateHint
{
	static constexpr HintCategory classCategory = HINTCAT_COMMENTS;
	CommentHint() : UpdateHint(classCategory) { type = HINT_MODCOMMENTS; }
};

OPENMPT_NAMESPACE_END