aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2024-05-14 14:17:44 -0400
committerSophie Zhang <sophie_zhang@brown.edu>2024-05-14 14:17:44 -0400
commit1e6d483091131db07b30e96d0910c858eb4f37c4 (patch)
tree9975ddef5dd273df19507adca53718066c888dcc
parent0201c8b4d52932760d87686424cdc0a4d39e60bd (diff)
add fields to customization
-rw-r--r--src/client/apis/gpt/customization.ts40
-rw-r--r--src/client/views/nodes/trails/CubicBezierEditor.tsx25
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx77
-rw-r--r--src/client/views/nodes/trails/SpringUtils.ts3
4 files changed, 45 insertions, 100 deletions
diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts
index 9c751f8bd..13129b23c 100644
--- a/src/client/apis/gpt/customization.ts
+++ b/src/client/apis/gpt/customization.ts
@@ -1,6 +1,4 @@
-import { ChatCompletionMessageParam } from 'openai/resources';
import { openai } from './setup';
-import { ClientOptions, OpenAI } from 'openai';
export enum CustomizationType {
PRES_TRAIL_SLIDE = 'trails',
@@ -18,15 +16,35 @@ const prompts: { [key: string]: PromptInfo } = {
},
};
+// Allows you to register properties that are customizable
export const addCustomizationProperty = (type: CustomizationType, name: string, description: string, values?: string[]) => {
values ? prompts[type].features.push({ name, description, values }) : prompts[type].features.push({ name, description });
};
-export const gptSlideProperties = ['title', 'presentation_transition', 'presentation_effect', 'presentation_effectDirection', 'presEffectTiming', 'config_zoom'];
+// All the registered fields, make sure to update during registration, this
+// includes most fields but is not yet fully comprehensive
+export const gptSlideProperties = [
+ 'title',
+ 'presentation_transition',
+ 'presEaseFunc',
+ 'presentation_effect',
+ 'presentation_effectDirection',
+ 'presEffectTiming',
+ 'config_zoom',
+ 'presPlayAudio',
+ 'presentation_zoomText',
+ 'presentation_hideBefore',
+ 'presentation_hide',
+ 'presentation_hideAfter',
+ 'presentation_openInLightbox',
+];
+// Registers slide properties
const setupPresSlideCustomization = () => {
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'title', 'is the title/name of the slide.');
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_transition', 'is a number in milliseconds for how long it should take to transition/move to a slide.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presEaseFunc', 'is the easing function for the movement to the slide.', ['Ease', 'Ease In', 'Ease Out', 'Ease Out', 'Ease In Out', 'Linear']);
+
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effect', 'is an effect applied to the slide when we transition to it.', ['None', 'Zoom', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']);
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_effectDirection', 'is what direction the effect is applied.', ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']);
addCustomizationProperty(
@@ -34,12 +52,21 @@ const setupPresSlideCustomization = () => {
'presEffectTiming',
"is a json object of the format: {type: string, stiffness: number, damping: number, mass: number}. Type is always “custom”. Controls the spring-based timing of the presentation effect animation. Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to match the user's description of how they want to animate the effect."
);
+
addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'config_zoom', 'is a number from 0 to 1.0 indicating the percentage we should zoom into the slide.');
+
+ // boolean values
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presPlayAudio', 'is a boolean value indicating if we should play audio when we go to the slide.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_zoomText', 'is a boolean value indicating if we should zoom into text selections when we go to the slide.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_hideBefore', 'is a boolean value indicating if we should hide the slide before going to it.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_hide', 'is a boolean value indicating if we should hide the slide during the presentation.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_hideAfter', 'is a boolean value indicating if we should hide the slide after going to it.');
+ addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_openInLightbox', 'is a boolean value indicating if we should open the slide in an overlay or lightbox view during the presentation.');
};
setupPresSlideCustomization();
-export const getSlideTransitionSuggestions = async (inputText: string, history?: string) => {
+export const getSlideTransitionSuggestions = async (inputText: string) => {
/**
* Prompt: Generate an entrance animations from slower and gentler
* to bouncier and more high energy
@@ -50,15 +77,12 @@ export const getSlideTransitionSuggestions = async (inputText: string, history?:
* effect: BOUNCE
* effectDirection: LEFT
* timingConfig: {
- *
- *
- *
* }
* }
*/
const prompt =
- "I want to generate four distinct types of slide effect animations. Return a json of the form {effect: string, stiffness: number, damping: number, mass: number}[] with four elements. Effect is the type of animation; its only possible values are ['Zoom', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']. Stiffness, damping, and mass Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to animate the effect.";
+ "I want to generate four distinct types of slide effect animations. Return a json of the form {effect: string, direction: string, stiffness: number, damping: number, mass: number}[] with four elements. Effect is the type of animation; its only possible values are ['Zoom', 'Fade in', 'Bounce', 'Flip', 'Rotate', 'Roll']. Direction is the direction that the animation starts from; its only possible values are ['Enter from left', 'Enter from right', 'Enter from bottom', 'Enter from Top', 'Enter from center']. Stiffness, damping, and mass control the physics-based properties of spring animations. This is used to create a more natural-looking timing, bouncy effects, etc. Use spring physics to adjust these parameters to animate the effect.";
const customInput = inputText ?? 'Make them as contrasting as possible with different effects and timings ranging from gentle to energetic.';
diff --git a/src/client/views/nodes/trails/CubicBezierEditor.tsx b/src/client/views/nodes/trails/CubicBezierEditor.tsx
index aba777e55..5f348ddd9 100644
--- a/src/client/views/nodes/trails/CubicBezierEditor.tsx
+++ b/src/client/views/nodes/trails/CubicBezierEditor.tsx
@@ -20,16 +20,11 @@ export const TIMING_DEFAULT_MAPPINGS = {
'ease-in-out': 'cubic-bezier(0.42, 0, 0.58, 1.0)',
};
+/**
+ * Visual editor for a bezier curve with draggable control points
+ * */
const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => {
const [animating, setAnimating] = useState(false);
- // const [cPoints, setCPoints] = useState(
- // currPoints
- // ? currPoints
- // : {
- // p1: [0.25, 0.1],
- // p2: [0.25, 1.0],
- // }
- // );
const [c1Down, setC1Down] = useState(false);
const [c2Down, setC2Down] = useState(false);
@@ -71,12 +66,6 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => {
};
};
- // useEffect(() => {
- // if (!easeFunc.startsWith('cubic')) {
- // setFunc(convertToPoints(easeFunc));
- // }
- // }, [easeFunc]);
-
useEffect(() => {
if (animating) {
setTimeout(() => {
@@ -96,10 +85,6 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => {
return;
}
- // setCPoints(prev => ({
- // ...prev,
- // p1: [roundToHundredth(prev.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p1[1] - e.movementY / EDITOR_WIDTH)],
- // }));
setFunc({
...currPoints,
p1: [roundToHundredth(currPoints.p1[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(currPoints.p1[1] - e.movementY / EDITOR_WIDTH)],
@@ -122,10 +107,6 @@ const CubicBezierEditor = ({ setFunc, currPoints, easeFunc }: Props) => {
return;
}
- // setCPoints(prev => ({
- // ...prev,
- // p2: [roundToHundredth(prev.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(prev.p2[1] - e.movementY / EDITOR_WIDTH)],
- // }));
setFunc({
...currPoints,
p2: [roundToHundredth(currPoints.p2[0] + e.movementX / EDITOR_WIDTH), roundToHundredth(currPoints.p2[1] - e.movementY / EDITOR_WIDTH)],
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 02233d241..a7a4e08e0 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -132,24 +132,28 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// default presets
{
effect: PresEffect.Bounce,
+ direction: PresEffectDirection.Left,
stiffness: 400,
damping: 15,
mass: 1,
},
{
effect: PresEffect.Fade,
+ direction: PresEffectDirection.Left,
stiffness: 100,
damping: 15,
mass: 1,
},
{
effect: PresEffect.Flip,
+ direction: PresEffectDirection.Left,
stiffness: 100,
damping: 15,
mass: 1,
},
{
- effect: PresEffect.Roll,
+ effect: PresEffect.Rotate,
+ direction: PresEffectDirection.Left,
stiffness: 100,
damping: 15,
mass: 1,
@@ -199,9 +203,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable easeDropdownVal = 'ease';
- // @observable bezierControlPoints: { p1: number[]; p2: number[] } = { p1: [0.67, 0.2], p2: [0.37, 0.88] };
@action setBezierControlPoints = (newPoints: { p1: number[]; p2: number[] }) => {
- // this.bezierControlPoints = newPoints;
this.setEaseFunc(this.activeItem, `cubic-bezier(${newPoints.p1[0]}, ${newPoints.p1[1]}, ${newPoints.p2[0]}, ${newPoints.p2[1]})`);
};
@@ -391,16 +393,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
customizeAnimations = async (input: string) => {
- // const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect';
- // if (!this.slideToModify) return;
this.setIsLoading(true);
-
try {
const res = await getSlideTransitionSuggestions(this.animationChat);
if (typeof res === 'string') {
const resObj = JSON.parse(res);
console.log('Parsed GPT Result ', resObj);
- // this.activeItem
this.setGeneratedAnimations(resObj as AnimationSettings[]);
}
} catch (err) {
@@ -412,7 +410,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
customizeWithGPT = async (input: string) => {
// const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect';
- // if (!this.slideToModify) return;
this.setIsRecording(false);
this.setIsLoading(true);
@@ -436,7 +433,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (typeof res === 'string') {
const resObj = JSON.parse(res);
console.log('Parsed GPT Result ', resObj);
- // this.activeItem
for (let key in resObj) {
if (resObj[key]) {
console.log('typeof property', typeof resObj[key]);
@@ -1733,25 +1729,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
valueLabelDisplay="auto"
/>
</div>
- // <input
- // type="range"
- // step={step}
- // min={min}
- // max={max}
- // value={value}
- // readOnly={true}
- // style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
- // className={`toolbar-slider ${active ? '' : 'none'}`}
- // onPointerDown={e => {
- // PresBox._sliderBatch = UndoManager.StartBatch('pres slider');
- // document.addEventListener('pointerup', PresBox.endBatch, true);
- // e.stopPropagation();
- // }}
- // onChange={e => {
- // e.stopPropagation();
- // change(e.target.value);
- // }}
- // />
);
};
@@ -1822,14 +1799,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
Lightbox
</div>
</Tooltip>
- {/* <Tooltip title={<div className="dash-tooltip">Transition movement style</div>}>
- <div
- className="ribbon-toggle"
- style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presEaseFunc === 'ease' ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
- onClick={() => this.updateEaseFunc(activeItem)}>
- {`${StrCast(activeItem.presEaseFunc, 'ease')}`}
- </div>
- </Tooltip> */}
</div>
{[DocumentType.AUDIO, DocumentType.VID].includes(targetType as any as DocumentType) ? null : (
<>
@@ -1838,14 +1807,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
<input className="presBox-input" type="number" readOnly={true} value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
</div>
- {/* <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
- <div className="ribbon-propertyUpDownItem" onClick={() => this.updateDurationTime(String(duration), 1000)}>
- <FontAwesomeIcon icon={'caret-up'} />
- </div>
- <div className="ribbon-propertyUpDownItem" onClick={() => this.updateDurationTime(String(duration), -1000)}>
- <FontAwesomeIcon icon={'caret-down'} />
- </div>
- </div> */}
</div>
{PresBox.inputter('0.1', '0.1', '20', duration, targetType !== DocumentType.AUDIO, this.updateDurationTime)}
<div className={'slider-headers'} style={{ display: targetType === DocumentType.AUDIO ? 'none' : 'grid' }}>
@@ -2020,11 +1981,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="pres-chat">
<div className="pres-chatbox-container">
<ReactTextareaAutosize
- // ref={r => (this._inputref = r)}
- // minRows={1}
placeholder="Describe how you would like to modify the slide properties."
className="pres-chatbox"
- // autoFocus={true}
value={this.chatInput}
onChange={e => {
this.setChatInput(e.target.value);
@@ -2118,9 +2076,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
setSelectedVal={val => {
if (typeof val === 'string') {
if (val !== 'custom') {
- this.setBezierEditorVisibility(true);
this.setEaseFunc(this.activeItem, val);
} else {
+ this.setBezierEditorVisibility(true);
this.setEaseFunc(this.activeItem, TIMING_DEFAULT_MAPPINGS.ease);
}
}
@@ -2157,11 +2115,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="pres-chat">
<div className="pres-chatbox-container">
<ReactTextareaAutosize
- // ref={r => (this._inputref2 = r)}
- // minRows={1}
placeholder="Customize prompt for effect suggestions. Leave blank for random results."
className="pres-chatbox"
- // autoFocus={true}
value={this.animationChat}
onChange={e => {
this.setAnimationChat(e.target.value);
@@ -2206,6 +2161,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
className="presBox-effect-container"
onClick={() => {
this.updateEffect(elem.effect, false);
+ this.updateEffectDirection(elem.direction);
this.updateEffectTiming(this.activeItem, {
type: SpringType.CUSTOM,
stiffness: elem.stiffness,
@@ -2213,7 +2169,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
mass: elem.mass,
});
}}>
- <SlideEffect dir={PresEffectDirection.Left as PresEffectDirection} presEffect={elem.effect as PresEffect} tension={elem.stiffness} friction={elem.damping} mass={elem.mass} infinite>
+ <SlideEffect dir={elem.direction as PresEffectDirection} presEffect={elem.effect as PresEffect} tension={elem.stiffness} friction={elem.damping} mass={elem.mass} infinite>
<div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[i] }}></div>
</SlideEffect>
</div>
@@ -2569,23 +2525,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/>
<div>On slide change</div>
</div>
- {/* <div className="checkbox-container">
- <input className="presBox-checkbox"
- type="checkbox"
- onChange={() => activeItem.mediaStop = "afterSlide"}
- checked={activeItem.mediaStop === "afterSlide"}
- />
- <div className="checkbox-dropdown">
- After chosen slide
- <select className="presBox-viewPicker"
- style={{ opacity: activeItem.mediaStop === "afterSlide" && this.itemIndex !== this.childDocs.length - 1 ? 1 : 0.3 }}
- onPointerDown={e => e.stopPropagation()}
- onChange={this.mediaStopChanged}
- value={mediaStopDocStr}>
- {this.mediaStopSlides}
- </select>
- </div>
- </div> */}
</div>
</div>
</div>
diff --git a/src/client/views/nodes/trails/SpringUtils.ts b/src/client/views/nodes/trails/SpringUtils.ts
index 5f1c0c6a9..757f27e18 100644
--- a/src/client/views/nodes/trails/SpringUtils.ts
+++ b/src/client/views/nodes/trails/SpringUtils.ts
@@ -1,4 +1,4 @@
-import { PresEffect, PresMovement } from './PresEnums';
+import { PresEffect, PresEffectDirection, PresMovement } from './PresEnums';
export const springPreviewColors = ['rgb(37, 161, 255)', 'rgb(99, 37, 255)', 'rgb(182, 37, 255)', 'rgb(255, 37, 168)'];
// the type of slide effect timing (spring-driven)
@@ -21,6 +21,7 @@ export interface SpringSettings {
export interface AnimationSettings {
effect: PresEffect;
+ direction: PresEffectDirection;
stiffness: number;
damping: number;
mass: number;